Commit 38971822 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[turbofan] Add AllocateHeapNumberStub to avoid runtime call.

TEST=unittests
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/703473004

Cr-Commit-Position: refs/heads/master@{#25107}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25107 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e56d4b92
......@@ -152,6 +152,15 @@ void TransitionElementsKindDescriptor::Initialize(
}
void AllocateHeapNumberDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// register state
// cp -- context
Register registers[] = {cp};
data->Initialize(arraysize(registers), registers, nullptr);
}
void ArrayConstructorConstantArgCountDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// register state
......
......@@ -185,6 +185,14 @@ void TransitionElementsKindDescriptor::Initialize(
}
void AllocateHeapNumberDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// cp: context
Register registers[] = {cp};
data->Initialize(arraysize(registers), registers, nullptr);
}
void ArrayConstructorConstantArgCountDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// cp: context
......
......@@ -103,6 +103,13 @@ Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
}
// static
Callable CodeFactory::AllocateHeapNumber(Isolate* isolate) {
AllocateHeapNumberStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::CallFunction(Isolate* isolate, int argc,
CallFunctionFlags flags) {
......
......@@ -55,9 +55,13 @@ class CodeFactory FINAL {
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag);
static Callable AllocateHeapNumber(Isolate* isolate);
static Callable CallFunction(Isolate* isolate, int argc,
CallFunctionFlags flags);
};
}
}
} // namespace internal
} // namespace v8
#endif // V8_CODE_FACTORY_H_
......@@ -883,6 +883,22 @@ Handle<Code> TransitionElementsKindStub::GenerateCode() {
return DoGenerateCode(this);
}
template <>
HValue* CodeStubGraphBuilder<AllocateHeapNumberStub>::BuildCodeStub() {
HValue* result =
Add<HAllocate>(Add<HConstant>(HeapNumber::kSize), HType::HeapNumber(),
NOT_TENURED, HEAP_NUMBER_TYPE);
AddStoreMapConstant(result, isolate()->factory()->heap_number_map());
return result;
}
Handle<Code> AllocateHeapNumberStub::GenerateCode() {
return DoGenerateCode(this);
}
HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
ElementsKind kind,
AllocationSiteOverrideMode override_mode,
......
......@@ -697,6 +697,13 @@ void TransitionElementsKindStub::InitializeDescriptor(
}
void AllocateHeapNumberStub::InitializeDescriptor(
CodeStubDescriptor* descriptor) {
descriptor->Initialize(
Runtime::FunctionForId(Runtime::kAllocateHeapNumber)->entry);
}
void CompareNilICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
descriptor->Initialize(FUNCTION_ADDR(CompareNilIC_Miss));
descriptor->SetMissHandler(
......
......@@ -51,6 +51,7 @@ namespace internal {
V(StubFailureTrampoline) \
V(SubString) \
/* HydrogenCodeStubs */ \
V(AllocateHeapNumber) \
V(ArrayNArgumentsConstructor) \
V(ArrayNoArgumentConstructor) \
V(ArraySingleArgumentConstructor) \
......@@ -2113,6 +2114,17 @@ class TransitionElementsKindStub : public HydrogenCodeStub {
};
class AllocateHeapNumberStub FINAL : public HydrogenCodeStub {
public:
explicit AllocateHeapNumberStub(Isolate* isolate)
: HydrogenCodeStub(isolate) {}
private:
DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
};
class ArrayConstructorStubBase : public HydrogenCodeStub {
public:
ArrayConstructorStubBase(Isolate* isolate,
......
......@@ -4,6 +4,7 @@
#include "src/compiler/change-lowering.h"
#include "src/code-factory.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
......@@ -66,19 +67,16 @@ Node* ChangeLowering::SmiShiftBitsConstant() {
Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) {
// The AllocateHeapNumber() runtime function does not use the context, so we
// can safely pass in Smi zero here.
// The AllocateHeapNumberStub does not use the context, so we can safely pass
// in Smi zero here.
Callable callable = CodeFactory::AllocateHeapNumber(isolate());
CallDescriptor* descriptor = linkage()->GetStubCallDescriptor(
callable.descriptor(), 0, CallDescriptor::kNoFlags);
Node* target = jsgraph()->HeapConstant(callable.code());
Node* context = jsgraph()->ZeroConstant();
Node* effect = graph()->NewNode(common()->ValueEffect(1), value);
const Runtime::Function* function =
Runtime::FunctionForId(Runtime::kAllocateHeapNumber);
DCHECK_EQ(0, function->nargs);
CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(
function->function_id, 0, Operator::kNoProperties);
Node* heap_number = graph()->NewNode(
common()->Call(desc), jsgraph()->CEntryStubConstant(),
jsgraph()->ExternalConstant(ExternalReference(function, isolate())),
jsgraph()->Int32Constant(function->nargs), context, effect, control);
Node* heap_number = graph()->NewNode(common()->Call(descriptor), target,
context, effect, control);
Node* store = graph()->NewNode(
machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)),
heap_number, HeapNumberValueIndexConstant(), value, heap_number, control);
......
......@@ -155,6 +155,15 @@ void TransitionElementsKindDescriptor::Initialize(
}
void AllocateHeapNumberDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// register state
// esi -- context
Register registers[] = {esi};
data->Initialize(arraysize(registers), registers, nullptr);
}
void ArrayConstructorConstantArgCountDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// register state
......
......@@ -33,6 +33,7 @@ class PlatformInterfaceDescriptor;
V(CallConstruct) \
V(RegExpConstructResult) \
V(TransitionElementsKind) \
V(AllocateHeapNumber) \
V(ArrayConstructorConstantArgCount) \
V(ArrayConstructor) \
V(InternalArrayConstructorConstantArgCount) \
......@@ -346,6 +347,12 @@ class TransitionElementsKindDescriptor : public CallInterfaceDescriptor {
};
class AllocateHeapNumberDescriptor : public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR(AllocateHeapNumberDescriptor, CallInterfaceDescriptor)
};
class ArrayConstructorConstantArgCountDescriptor
: public CallInterfaceDescriptor {
public:
......
......@@ -155,6 +155,15 @@ void TransitionElementsKindDescriptor::Initialize(
}
void AllocateHeapNumberDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// register state
// rsi -- context
Register registers[] = {rsi};
data->Initialize(arraysize(registers), registers, nullptr);
}
void ArrayConstructorConstantArgCountDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// register state
......
......@@ -79,13 +79,9 @@ class ChangeLoweringTest : public GraphTest {
Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
return IsCall(
_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
CEntryStub(isolate(), 1).GetCode())),
IsExternalConstant(ExternalReference(
Runtime::FunctionForId(Runtime::kAllocateHeapNumber), isolate())),
IsInt32Constant(0), IsNumberConstant(0.0), effect_matcher,
control_matcher);
return IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
AllocateHeapNumberStub(isolate()).GetCode())),
IsNumberConstant(0.0), effect_matcher, control_matcher);
}
Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher) {
......
......@@ -332,15 +332,66 @@ class IsProjectionMatcher FINAL : public NodeMatcher {
};
class IsCallMatcher FINAL : public NodeMatcher {
class IsCall2Matcher FINAL : public NodeMatcher {
public:
IsCallMatcher(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& value2_matcher,
const Matcher<Node*>& value3_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher)
IsCall2Matcher(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kCall),
descriptor_matcher_(descriptor_matcher),
value0_matcher_(value0_matcher),
value1_matcher_(value1_matcher),
effect_matcher_(effect_matcher),
control_matcher_(control_matcher) {}
virtual void DescribeTo(std::ostream* os) const OVERRIDE {
NodeMatcher::DescribeTo(os);
*os << " whose value0 (";
value0_matcher_.DescribeTo(os);
*os << ") and value1 (";
value1_matcher_.DescribeTo(os);
*os << ") and effect (";
effect_matcher_.DescribeTo(os);
*os << ") and control (";
control_matcher_.DescribeTo(os);
*os << ")";
}
virtual bool MatchAndExplain(Node* node,
MatchResultListener* listener) const OVERRIDE {
return (NodeMatcher::MatchAndExplain(node, listener) &&
PrintMatchAndExplain(OpParameter<CallDescriptor*>(node),
"descriptor", descriptor_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
"value0", value0_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
"value1", value1_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
effect_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetControlInput(node),
"control", control_matcher_, listener));
}
private:
const Matcher<CallDescriptor*> descriptor_matcher_;
const Matcher<Node*> value0_matcher_;
const Matcher<Node*> value1_matcher_;
const Matcher<Node*> effect_matcher_;
const Matcher<Node*> control_matcher_;
};
class IsCall4Matcher FINAL : public NodeMatcher {
public:
IsCall4Matcher(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& value2_matcher,
const Matcher<Node*>& value3_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kCall),
descriptor_matcher_(descriptor_matcher),
value0_matcher_(value0_matcher),
......@@ -835,6 +886,17 @@ Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
}
Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
return MakeMatcher(new IsCall2Matcher(descriptor_matcher, value0_matcher,
value1_matcher, effect_matcher,
control_matcher));
}
Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
const Matcher<Node*>& value1_matcher,
......@@ -842,7 +904,7 @@ Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value3_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
return MakeMatcher(new IsCallMatcher(
return MakeMatcher(new IsCall4Matcher(
descriptor_matcher, value0_matcher, value1_matcher, value2_matcher,
value3_matcher, effect_matcher, control_matcher));
}
......
......@@ -58,6 +58,11 @@ Matcher<Node*> IsPhi(const Matcher<MachineType>& type_matcher,
const Matcher<Node*>& merge_matcher);
Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
const Matcher<Node*>& base_matcher);
Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher,
const Matcher<Node*>& value1_matcher,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment