Reviewers: fschneider,
Description:
Port function call type-feedback cells to x64 and ARM.
[email protected]
BUG=v8:1857,v8:2079
Please review this at https://chromiumcodereview.appspot.com/10124008/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/arm/code-stubs-arm.cc
M src/arm/full-codegen-arm.cc
M src/x64/code-stubs-x64.cc
M src/x64/full-codegen-x64.cc
Index: src/arm/code-stubs-arm.cc
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index
2f14d191b0598d9f27be0eab01fdb90493a76be9..bcd3f58e31cbc8652a09a0eccfec94014b53fa5c
100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -5169,9 +5169,9 @@ void CallFunctionStub::Generate(MacroAssembler* masm)
{
__ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
__ b(ne, &call);
// Patch the receiver on the stack with the global receiver object.
- __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
- __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
- __ str(r2, MemOperand(sp, argc_ * kPointerSize));
+ __ ldr(r3, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalReceiverOffset));
+ __ str(r3, MemOperand(sp, argc_ * kPointerSize));
__ bind(&call);
}
@@ -5179,9 +5179,13 @@ void CallFunctionStub::Generate(MacroAssembler*
masm) {
// r1: pushed function (to be verified)
__ JumpIfSmi(r1, &non_function);
// Get the map of the function object.
- __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
+ __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
__ b(ne, &slow);
+ if (RecordCallTarget()) {
+ GenerateRecordCallTarget(masm);
+ }
+
// Fast-case: Invoke the function now.
// r1: pushed function
ParameterCount actual(argc_);
@@ -5205,6 +5209,15 @@ void CallFunctionStub::Generate(MacroAssembler*
masm) {
// Slow-case: Non-function called.
__ bind(&slow);
+ if (RecordCallTarget()) {
+ // If there is a call target cache, mark it megamorphic in the
+ // non-function case. MegamorphicSentinel is an immortal immovable
+ // object (undefined) so no write barrier is needed.
+ ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
+ masm->isolate()->heap()->undefined_value());
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+ __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ }
// Check for function proxy.
__ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
__ b(ne, &non_function);
Index: src/arm/full-codegen-arm.cc
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index
e7555cba051eedc43d1d45078120e99e5769ef66..e214dcc348c9caefff86dcb91f15ecb1fa4da8d0
100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -2361,6 +2361,18 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr,
CallFunctionFlags flags) {
}
// Record source position for debugger.
SetSourcePosition(expr->position());
+
+ // Record call targets in unoptimized code, but not in the snapshot.
+ if (!Serializer::enabled()) {
+ flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
+ Handle<Object> uninitialized =
+ TypeFeedbackCells::UninitializedSentinel(isolate());
+ Handle<JSGlobalPropertyCell> cell =
+ isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ RecordTypeFeedbackCell(expr->id(), cell);
+ __ mov(r2, Operand(cell));
+ }
+
CallFunctionStub stub(arg_count, flags);
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
Index: src/x64/code-stubs-x64.cc
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index
ce9067cda9af429ad5f087fd386fd5703db7f2ad..d179d2a5d5049aefdac27249130df673f58e9eb4
100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -3628,8 +3628,9 @@ static void GenerateRecordCallTarget(MacroAssembler*
masm) {
void CallFunctionStub::Generate(MacroAssembler* masm) {
- // rdi : the function to call
// rbx : cache cell for call target
+ // rdi : the function to call
+ Isolate* isolate = masm->isolate();
Label slow, non_function;
// The receiver might implicitly be the global object. This is
@@ -3644,9 +3645,9 @@ void CallFunctionStub::Generate(MacroAssembler* masm)
{
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &call, Label::kNear);
// Patch the receiver on the stack with the global receiver object.
- __ movq(rbx, GlobalObjectOperand());
- __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
- __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rbx);
+ __ movq(rcx, GlobalObjectOperand());
+ __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
+ __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rcx);
__ bind(&call);
}
@@ -3656,6 +3657,10 @@ void CallFunctionStub::Generate(MacroAssembler*
masm) {
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &slow);
+ if (RecordCallTarget()) {
+ GenerateRecordCallTarget(masm);
+ }
+
// Fast-case: Just invoke the function.
ParameterCount actual(argc_);
@@ -3678,6 +3683,13 @@ void CallFunctionStub::Generate(MacroAssembler*
masm) {
// Slow-case: Non-function called.
__ bind(&slow);
+ if (RecordCallTarget()) {
+ // If there is a call target cache, mark it megamorphic in the
+ // non-function case. MegamorphicSentinel is an immortal immovable
+ // object (undefined) so no write barrier is needed.
+ __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+ TypeFeedbackCells::MegamorphicSentinel(isolate));
+ }
// Check for function proxy.
__ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
__ j(not_equal, &non_function);
Index: src/x64/full-codegen-x64.cc
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index
e0000f8743e78e3ab3c1005a35291a1a8f7f68ac..a6c4c99785e5d45f39389e49e5bb9708b9b97439
100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -2273,6 +2273,18 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr,
CallFunctionFlags flags) {
}
// Record source position for debugger.
SetSourcePosition(expr->position());
+
+ // Record call targets in unoptimized code, but not in the snapshot.
+ if (!Serializer::enabled()) {
+ flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
+ Handle<Object> uninitialized =
+ TypeFeedbackCells::UninitializedSentinel(isolate());
+ Handle<JSGlobalPropertyCell> cell =
+ isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ RecordTypeFeedbackCell(expr->id(), cell);
+ __ Move(rbx, cell);
+ }
+
CallFunctionStub stub(arg_count, flags);
__ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev