| // Copyright 2014 the V8 project authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/compiler/js-graph.h" | |
| #include "src/code-factory.h" | |
| #include "src/compiler/node-properties.h" | |
| #include "src/compiler/typer.h" | |
| #include "src/objects-inl.h" | |
| namespace v8 { | |
| namespace internal { | |
| namespace compiler { | |
| #define GET_CACHED_FIELD(ptr, expr) (*(ptr)) ? *(ptr) : (*(ptr) = (expr)) | |
| #define DEFINE_GETTER(name, expr) \ | |
| Node* JSGraph::name() { return GET_CACHED_FIELD(&name##_, expr); } | |
| Node* JSGraph::CEntryStubConstant(int result_size, SaveFPRegsMode save_doubles, | |
| ArgvMode argv_mode, bool builtin_exit_frame) { | |
| if (save_doubles == kDontSaveFPRegs && argv_mode == kArgvOnStack) { | |
| DCHECK(result_size >= 1 && result_size <= 3); | |
| if (!builtin_exit_frame) { | |
| Node** ptr = nullptr; | |
| if (result_size == 1) { | |
| ptr = &CEntryStub1Constant_; | |
| } else if (result_size == 2) { | |
| ptr = &CEntryStub2Constant_; | |
| } else { | |
| DCHECK_EQ(3, result_size); | |
| ptr = &CEntryStub3Constant_; | |
| } | |
| return GET_CACHED_FIELD(ptr, HeapConstant(CodeFactory::CEntry( | |
| isolate(), result_size, save_doubles, | |
| argv_mode, builtin_exit_frame))); | |
| } | |
| Node** ptr = builtin_exit_frame ? &CEntryStub1WithBuiltinExitFrameConstant_ | |
| : &CEntryStub1Constant_; | |
| return GET_CACHED_FIELD(ptr, HeapConstant(CodeFactory::CEntry( | |
| isolate(), result_size, save_doubles, | |
| argv_mode, builtin_exit_frame))); | |
| } | |
| return HeapConstant(CodeFactory::CEntry(isolate(), result_size, save_doubles, | |
| argv_mode, builtin_exit_frame)); | |
| } | |
| Node* JSGraph::Constant(Handle<Object> value) { | |
| // Dereference the handle to determine if a number constant or other | |
| // canonicalized node can be used. | |
| if (value->IsNumber()) { | |
| return Constant(value->Number()); | |
| } else if (value->IsUndefined(isolate())) { | |
| return UndefinedConstant(); | |
| } else if (value->IsTrue(isolate())) { | |
| return TrueConstant(); | |
| } else if (value->IsFalse(isolate())) { | |
| return FalseConstant(); | |
| } else if (value->IsNull(isolate())) { | |
| return NullConstant(); | |
| } else if (value->IsTheHole(isolate())) { | |
| return TheHoleConstant(); | |
| } else { | |
| return HeapConstant(Handle<HeapObject>::cast(value)); | |
| } | |
| } | |
| Node* JSGraph::Constant(const ObjectRef& ref) { | |
| if (ref.IsSmi()) return Constant(ref.AsSmi()); | |
| OddballType oddball_type = ref.oddball_type(); | |
| if (ref.IsHeapNumber()) { | |
| return Constant(ref.AsHeapNumber().value()); | |
| } else if (oddball_type == OddballType::kUndefined) { | |
| DCHECK( | |
| ref.object<Object>().equals(isolate()->factory()->undefined_value())); | |
| return UndefinedConstant(); | |
| } else if (oddball_type == OddballType::kNull) { | |
| DCHECK(ref.object<Object>().equals(isolate()->factory()->null_value())); | |
| return NullConstant(); | |
| } else if (oddball_type == OddballType::kHole) { | |
| DCHECK(ref.object<Object>().equals(isolate()->factory()->the_hole_value())); | |
| return TheHoleConstant(); | |
| } else if (oddball_type == OddballType::kBoolean) { | |
| if (ref.object<Object>().equals(isolate()->factory()->true_value())) { | |
| return TrueConstant(); | |
| } else { | |
| DCHECK(ref.object<Object>().equals(isolate()->factory()->false_value())); | |
| return FalseConstant(); | |
| } | |
| } else { | |
| return HeapConstant(ref.object<HeapObject>()); | |
| } | |
| } | |
| Node* JSGraph::Constant(double value) { | |
| if (bit_cast<int64_t>(value) == bit_cast<int64_t>(0.0)) return ZeroConstant(); | |
| if (bit_cast<int64_t>(value) == bit_cast<int64_t>(1.0)) return OneConstant(); | |
| return NumberConstant(value); | |
| } | |
| Node* JSGraph::Constant(int32_t value) { | |
| if (value == 0) return ZeroConstant(); | |
| if (value == 1) return OneConstant(); | |
| return NumberConstant(value); | |
| } | |
| Node* JSGraph::Constant(uint32_t value) { | |
| if (value == 0) return ZeroConstant(); | |
| if (value == 1) return OneConstant(); | |
| return NumberConstant(value); | |
| } | |
| Node* JSGraph::NumberConstant(double value) { | |
| Node** loc = cache_.FindNumberConstant(value); | |
| if (*loc == nullptr) { | |
| *loc = graph()->NewNode(common()->NumberConstant(value)); | |
| } | |
| return *loc; | |
| } | |
| Node* JSGraph::HeapConstant(Handle<HeapObject> value) { | |
| Node** loc = cache_.FindHeapConstant(value); | |
| if (*loc == nullptr) { | |
| *loc = graph()->NewNode(common()->HeapConstant(value)); | |
| } | |
| return *loc; | |
| } | |
| void JSGraph::GetCachedNodes(NodeVector* nodes) { | |
| cache_.GetCachedNodes(nodes); | |
| #define DO_CACHED_FIELD(name) \ | |
| if (name##_) nodes->push_back(name##_); | |
| CACHED_GLOBAL_LIST(DO_CACHED_FIELD) | |
| CACHED_CENTRY_LIST(DO_CACHED_FIELD) | |
| #undef DO_CACHED_FIELD | |
| } | |
| DEFINE_GETTER(AllocateInNewSpaceStubConstant, | |
| HeapConstant(BUILTIN_CODE(isolate(), AllocateInNewSpace))) | |
| DEFINE_GETTER(AllocateInOldSpaceStubConstant, | |
| HeapConstant(BUILTIN_CODE(isolate(), AllocateInOldSpace))) | |
| DEFINE_GETTER(ArrayConstructorStubConstant, | |
| HeapConstant(BUILTIN_CODE(isolate(), ArrayConstructorImpl))) | |
| DEFINE_GETTER(ToNumberBuiltinConstant, | |
| HeapConstant(BUILTIN_CODE(isolate(), ToNumber))) | |
| DEFINE_GETTER(EmptyFixedArrayConstant, | |
| HeapConstant(factory()->empty_fixed_array())) | |
| DEFINE_GETTER(EmptyStringConstant, HeapConstant(factory()->empty_string())) | |
| DEFINE_GETTER(FixedArrayMapConstant, HeapConstant(factory()->fixed_array_map())) | |
| DEFINE_GETTER(PropertyArrayMapConstant, | |
| HeapConstant(factory()->property_array_map())) | |
| DEFINE_GETTER(FixedDoubleArrayMapConstant, | |
| HeapConstant(factory()->fixed_double_array_map())) | |
| DEFINE_GETTER(HeapNumberMapConstant, HeapConstant(factory()->heap_number_map())) | |
| DEFINE_GETTER(OptimizedOutConstant, HeapConstant(factory()->optimized_out())) | |
| DEFINE_GETTER(StaleRegisterConstant, HeapConstant(factory()->stale_register())) | |
| DEFINE_GETTER(UndefinedConstant, HeapConstant(factory()->undefined_value())) | |
| DEFINE_GETTER(TheHoleConstant, HeapConstant(factory()->the_hole_value())) | |
| DEFINE_GETTER(TrueConstant, HeapConstant(factory()->true_value())) | |
| DEFINE_GETTER(FalseConstant, HeapConstant(factory()->false_value())) | |
| DEFINE_GETTER(NullConstant, HeapConstant(factory()->null_value())) | |
| DEFINE_GETTER(ZeroConstant, NumberConstant(0.0)) | |
| DEFINE_GETTER(OneConstant, NumberConstant(1.0)) | |
| DEFINE_GETTER(MinusOneConstant, NumberConstant(-1.0)) | |
| DEFINE_GETTER(NaNConstant, | |
| NumberConstant(std::numeric_limits<double>::quiet_NaN())) | |
| DEFINE_GETTER(EmptyStateValues, | |
| graph()->NewNode(common()->StateValues(0, | |
| SparseInputMask::Dense()))) | |
| DEFINE_GETTER(SingleDeadTypedStateValues, | |
| graph()->NewNode(common()->TypedStateValues( | |
| new (graph()->zone()->New(sizeof(ZoneVector<MachineType>))) | |
| ZoneVector<MachineType>(0, graph()->zone()), | |
| SparseInputMask(SparseInputMask::kEndMarker << 1)))) | |
| #undef DEFINE_GETTER | |
| #undef GET_CACHED_FIELD | |
| } // namespace compiler | |
| } // namespace internal | |
| } // namespace v8 |