blob: 43a4beadeeb7542c4f36193ad4b62a7da6578f93 [file] [log] [blame]
// 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/codegen/code-factory.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/typer.h"
#include "src/objects/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.AsHeapObject().GetHeapObjectType().oddball_type();
if (ref.IsHeapNumber()) {
return Constant(ref.AsHeapNumber().value());
} else if (oddball_type == OddballType::kUndefined) {
DCHECK(ref.object().equals(isolate()->factory()->undefined_value()));
return UndefinedConstant();
} else if (oddball_type == OddballType::kNull) {
DCHECK(ref.object().equals(isolate()->factory()->null_value()));
return NullConstant();
} else if (oddball_type == OddballType::kHole) {
DCHECK(ref.object().equals(isolate()->factory()->the_hole_value()));
return TheHoleConstant();
} else if (oddball_type == OddballType::kBoolean) {
if (ref.object().equals(isolate()->factory()->true_value())) {
return TrueConstant();
} else {
DCHECK(ref.object().equals(isolate()->factory()->false_value()));
return FalseConstant();
}
} else {
return HeapConstant(ref.AsHeapObject().object());
}
}
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::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(AllocateInYoungGenerationStubConstant,
HeapConstant(BUILTIN_CODE(isolate(), AllocateInYoungGeneration)))
DEFINE_GETTER(AllocateRegularInYoungGenerationStubConstant,
HeapConstant(BUILTIN_CODE(isolate(),
AllocateRegularInYoungGeneration)))
DEFINE_GETTER(AllocateInOldGenerationStubConstant,
HeapConstant(BUILTIN_CODE(isolate(), AllocateInOldGeneration)))
DEFINE_GETTER(AllocateRegularInOldGenerationStubConstant,
HeapConstant(BUILTIN_CODE(isolate(),
AllocateRegularInOldGeneration)))
DEFINE_GETTER(ArrayConstructorStubConstant,
HeapConstant(BUILTIN_CODE(isolate(), ArrayConstructorImpl)))
DEFINE_GETTER(BigIntMapConstant, HeapConstant(factory()->bigint_map()))
DEFINE_GETTER(BooleanMapConstant, HeapConstant(factory()->boolean_map()))
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