Simplify dispatch in FullCodeGenerator::VisitCall a bit.

This makes FullCodeGenerator::VisitCall be independent of the target
architecture. Only the EmitPossiblyEvalCall case was dependent and is
hoisted into an emitter method.

R=rossberg@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#31693}
This commit is contained in:
mstarzinger 2015-10-30 07:42:05 -07:00 committed by Commit bot
parent 06eb555fa3
commit 0b293d877c
12 changed files with 306 additions and 598 deletions

View File

@ -3572,6 +3572,14 @@ void MacroAssembler::TryGetFunctionPrototype(Register function, Register result,
}
void MacroAssembler::PushRoot(Heap::RootListIndex index) {
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
LoadRoot(temp, index);
Push(temp);
}
void MacroAssembler::CompareRoot(const Register& obj,
Heap::RootListIndex index) {
UseScratchRegisterScope temps(this);

View File

@ -1461,6 +1461,9 @@ class MacroAssembler : public Assembler {
// register.
void LoadElementsKindFromMap(Register result, Register map);
// Load the value from the root list and push it onto the stack.
void PushRoot(Heap::RootListIndex index);
// Compare the object in a register to a value from the root list.
void CompareRoot(const Register& obj, Heap::RootListIndex index);

View File

@ -3040,86 +3040,40 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call
// RuntimeHidden_asResolvePossiblyDirectEval to resolve the function we need
// to call. Then we call the resolved function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
PushCalleeAndWithBaseObject(expr);
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call
// RuntimeHidden_asResolvePossiblyDirectEval to resolve the function we need
// to call. Then we call the resolved function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r0);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
__ push(r1);
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r0);
}

View File

@ -2744,89 +2744,42 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
PushCalleeAndWithBaseObject(expr);
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ Peek(x10, (arg_count + 1) * kPointerSize);
__ Push(x10);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ Poke(x0, (arg_count + 1) * kPointerSize);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
// Call the evaluated function.
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ Peek(x1, (arg_count + 1) * kXRegSize);
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, x0);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ LoadRoot(x1, Heap::kUndefinedValueRootIndex);
__ Push(x1);
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ Peek(x10, (arg_count + 1) * kPointerSize);
__ Push(x10);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ Poke(x0, (arg_count + 1) * kPointerSize);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
// Call the evaluated function.
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ Peek(x1, (arg_count + 1) * kXRegSize);
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, x0);
}

View File

@ -1425,6 +1425,66 @@ void FullCodeGenerator::ExitTryBlock(int handler_index) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
switch (call_type) {
case Call::POSSIBLY_EVAL_CALL:
EmitPossiblyEvalCall(expr);
break;
case Call::GLOBAL_CALL:
EmitCallWithLoadIC(expr);
break;
case Call::LOOKUP_SLOT_CALL:
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
break;
case Call::NAMED_PROPERTY_CALL: {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
break;
}
case Call::KEYED_PROPERTY_CALL: {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
break;
}
case Call::NAMED_SUPER_PROPERTY_CALL:
EmitSuperCallWithLoadIC(expr);
break;
case Call::KEYED_SUPER_PROPERTY_CALL:
EmitKeyedSuperCallWithLoadIC(expr);
break;
case Call::SUPER_CALL:
EmitSuperConstructorCall(expr);
break;
case Call::OTHER_CALL:
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ PushRoot(Heap::kUndefinedValueRootIndex);
// Emit function call.
EmitCall(expr);
break;
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
}
void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }

View File

@ -477,6 +477,7 @@ class FullCodeGenerator: public AstVisitor {
void EmitSuperCallWithLoadIC(Call* expr);
void EmitKeyedCallWithLoadIC(Call* expr, Expression* key);
void EmitKeyedSuperCallWithLoadIC(Call* expr);
void EmitPossiblyEvalCall(Call* expr);
#define FOR_EACH_FULL_CODE_INTRINSIC(F) \
F(IsSmi) \

View File

@ -2929,83 +2929,38 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
PushCalleeAndWithBaseObject(expr);
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ push(Immediate(isolate()->factory()->undefined_value()));
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
}

View File

@ -3032,83 +3032,38 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(a1);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
__ push(a1);
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(a1);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
}

View File

@ -3034,83 +3034,38 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(a1);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
__ push(a1);
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(a1);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, v0);
}

View File

@ -3033,86 +3033,40 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
PushCalleeAndWithBaseObject(expr);
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
__ push(r4);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r3);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
__ push(r4);
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
__ push(r4);
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, r3);
}

View File

@ -2921,82 +2921,37 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and resolve
// eval.
__ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the callee.
__ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, rax);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ PushRoot(Heap::kUndefinedValueRootIndex);
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and resolve
// eval.
__ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the callee.
__ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, rax);
}

View File

@ -2922,83 +2922,38 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// through this function. Avoid early returns.
expr->return_is_recorded_ = false;
#endif
void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
Comment cmnt(masm_, "[ Call");
Expression* callee = expr->expression();
Call::CallType call_type = expr->GetCallType(isolate());
PushCalleeAndWithBaseObject(expr);
if (call_type == Call::POSSIBLY_EVAL_CALL) {
// In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
// to resolve the function we need to call. Then we call the resolved
// function using the given arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
} else if (call_type == Call::GLOBAL_CALL) {
EmitCallWithLoadIC(expr);
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
// Call to a lookup slot (dynamically introduced variable).
PushCalleeAndWithBaseObject(expr);
EmitCall(expr);
} else if (call_type == Call::NAMED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_PROPERTY_CALL) {
Property* property = callee->AsProperty();
VisitForStackValue(property->obj());
EmitKeyedCallWithLoadIC(expr, property->key());
} else if (call_type == Call::NAMED_SUPER_PROPERTY_CALL) {
EmitSuperCallWithLoadIC(expr);
} else if (call_type == Call::KEYED_SUPER_PROPERTY_CALL) {
EmitKeyedSuperCallWithLoadIC(expr);
} else if (call_type == Call::SUPER_CALL) {
EmitSuperConstructorCall(expr);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
VisitForStackValue(callee);
__ push(Immediate(isolate()->factory()->undefined_value()));
// Emit function call.
EmitCall(expr);
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
#ifdef DEBUG
// RecordJSReturnSite should have been called.
DCHECK(expr->return_is_recorded_);
#endif
// Push a copy of the function (found below the arguments) and
// resolve eval.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
// Touch up the stack with the resolved function.
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr, arg_count);
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
RecordJSReturnSite(expr);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
}