Commit b92ef0be authored by ager@chromium.org's avatar ager@chromium.org

MIPS: port Fix calls of strict mode function with an implicit receiver.

Port of r8040 to mips.

Original commit message:
Strict mode functions are to get 'undefined' as the receiver when
called with an implicit receiver. Modes are bad! It forces us to have
checks on all function calls.
This change attempts to limit the cost by passing information about
whether or not a call is with an implicit or explicit receiver in ecx
as part of the calling convention. The cost is setting ecx on all
calls and checking ecx on entry to strict mode functions.
Implicit/explicit receiver state has to be maintained by ICs. Various
stubs have to not clobber ecx or save and restore it.
CallFunction stub needs to check if the receiver is implicit when it
doesn't know from the context.

BUG=
TEST=

Review URL: http://codereview.chromium.org/6992051
Patch from Paul Lind <plind44@gmail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8050 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2489594d
...@@ -645,6 +645,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { ...@@ -645,6 +645,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// Set expected number of arguments to zero (not changing a0). // Set expected number of arguments to zero (not changing a0).
__ mov(a2, zero_reg); __ mov(a2, zero_reg);
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ SetCallKind(t1, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} }
...@@ -1102,6 +1103,8 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) { ...@@ -1102,6 +1103,8 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
// Preserve the function. // Preserve the function.
__ push(a1); __ push(a1);
// Push call kind information.
__ push(t1);
// Push the function on the stack as the argument to the runtime function. // Push the function on the stack as the argument to the runtime function.
__ push(a1); __ push(a1);
...@@ -1109,6 +1112,9 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) { ...@@ -1109,6 +1112,9 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
__ CallRuntime(Runtime::kLazyCompile, 1); __ CallRuntime(Runtime::kLazyCompile, 1);
// Calculate the entry point. // Calculate the entry point.
__ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag); __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag);
// Restore call kind information.
__ pop(t1);
// Restore saved function. // Restore saved function.
__ pop(a1); __ pop(a1);
...@@ -1126,12 +1132,17 @@ void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { ...@@ -1126,12 +1132,17 @@ void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
// Preserve the function. // Preserve the function.
__ push(a1); __ push(a1);
// Push call kind information.
__ push(t1);
// Push the function on the stack as the argument to the runtime function. // Push the function on the stack as the argument to the runtime function.
__ push(a1); __ push(a1);
__ CallRuntime(Runtime::kLazyRecompile, 1); __ CallRuntime(Runtime::kLazyRecompile, 1);
// Calculate the entry point. // Calculate the entry point.
__ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
// Restore call kind information.
__ pop(t1);
// Restore saved function. // Restore saved function.
__ pop(a1); __ pop(a1);
...@@ -1306,6 +1317,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { ...@@ -1306,6 +1317,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ Branch(&function, ne, a1, Operand(zero_reg)); __ Branch(&function, ne, a1, Operand(zero_reg));
__ mov(a2, zero_reg); // expected arguments is 0 for CALL_NON_FUNCTION __ mov(a2, zero_reg); // expected arguments is 0 for CALL_NON_FUNCTION
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
__ SetCallKind(t1, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
__ bind(&function); __ bind(&function);
...@@ -1321,6 +1333,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { ...@@ -1321,6 +1333,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
__ sra(a2, a2, kSmiTagSize); __ sra(a2, a2, kSmiTagSize);
__ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ SetCallKind(t1, CALL_AS_METHOD);
// Check formal and actual parameter counts. // Check formal and actual parameter counts.
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET, ne, a2, Operand(a0)); RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
...@@ -1500,6 +1513,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1500,6 +1513,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// -- a1: function (passed through to callee) // -- a1: function (passed through to callee)
// -- a2: expected arguments count // -- a2: expected arguments count
// -- a3: callee code entry // -- a3: callee code entry
// -- t1: call kind information
// ----------------------------------- // -----------------------------------
Label invoke, dont_adapt_arguments; Label invoke, dont_adapt_arguments;
......
...@@ -4655,34 +4655,22 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) { ...@@ -4655,34 +4655,22 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
void CallFunctionStub::Generate(MacroAssembler* masm) { void CallFunctionStub::Generate(MacroAssembler* masm) {
Label slow; Label slow;
// If the receiver might be a value (string, number or boolean) check // The receiver might implicitly be the global object. This is
// for this and box it if it is. // indicated by passing the hole as the receiver to the call
if (ReceiverMightBeValue()) { // function stub.
if (ReceiverMightBeImplicit()) {
Label call;
// Get the receiver from the stack. // Get the receiver from the stack.
// function, receiver [, arguments] // function, receiver [, arguments]
Label receiver_is_value, receiver_is_js_object; __ lw(t0, MemOperand(sp, argc_ * kPointerSize));
__ lw(a1, MemOperand(sp, argc_ * kPointerSize)); // Call as function is indicated with the hole.
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
// Check if receiver is a smi (which is a number value). __ Branch(&call, ne, t0, Operand(at));
__ JumpIfSmi(a1, &receiver_is_value); // Patch the receiver on the stack with the global receiver object.
__ lw(a1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
// Check if the receiver is a valid JS object. __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset));
__ GetObjectType(a1, a2, a2); __ sw(a1, MemOperand(sp, argc_ * kPointerSize));
__ Branch(&receiver_is_js_object, __ bind(&call);
ge,
a2,
Operand(FIRST_JS_OBJECT_TYPE));
// Call the runtime to box the value.
__ bind(&receiver_is_value);
// We need natives to execute this.
__ EnterInternalFrame();
__ push(a1);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ LeaveInternalFrame();
__ sw(v0, MemOperand(sp, argc_ * kPointerSize));
__ bind(&receiver_is_js_object);
} }
// Get the function to call from the stack. // Get the function to call from the stack.
...@@ -4699,7 +4687,19 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { ...@@ -4699,7 +4687,19 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
// Fast-case: Invoke the function now. // Fast-case: Invoke the function now.
// a1: pushed function // a1: pushed function
ParameterCount actual(argc_); ParameterCount actual(argc_);
__ InvokeFunction(a1, actual, JUMP_FUNCTION);
if (ReceiverMightBeImplicit()) {
Label call_as_function;
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&call_as_function, eq, t0, Operand(at));
__ InvokeFunction(a1, actual, JUMP_FUNCTION);
__ bind(&call_as_function);
}
__ InvokeFunction(a1,
actual,
JUMP_FUNCTION,
NullCallWrapper(),
CALL_AS_FUNCTION);
// Slow-case: Non-function called. // Slow-case: Non-function called.
__ bind(&slow); __ bind(&slow);
......
...@@ -147,6 +147,19 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { ...@@ -147,6 +147,19 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
} }
#endif #endif
// Strict mode functions need to replace the receiver with undefined
// when called as functions (without an explicit receiver
// object). t1 is zero for method calls and non-zero for function
// calls.
if (info->is_strict_mode()) {
Label ok;
__ Branch(&ok, eq, t1, Operand(zero_reg));
int receiver_offset = scope()->num_parameters() * kPointerSize;
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
__ sw(a2, MemOperand(sp, receiver_offset));
__ bind(&ok);
}
int locals_count = scope()->num_stack_slots(); int locals_count = scope()->num_stack_slots();
__ Push(ra, fp, cp, a1); __ Push(ra, fp, cp, a1);
...@@ -2105,7 +2118,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, ...@@ -2105,7 +2118,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
// Call the IC initialization code. // Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode);
EmitCallIC(ic, mode, expr->id()); EmitCallIC(ic, mode, expr->id());
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
...@@ -2115,8 +2128,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, ...@@ -2115,8 +2128,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
Expression* key, Expression* key) {
RelocInfo::Mode mode) {
// Load the key. // Load the key.
VisitForAccumulatorValue(key); VisitForAccumulatorValue(key);
...@@ -2141,7 +2153,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, ...@@ -2141,7 +2153,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
__ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key.
EmitCallIC(ic, mode, expr->id()); EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id());
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
...@@ -2255,7 +2267,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -2255,7 +2267,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT);
__ CallStub(&stub); __ CallStub(&stub);
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
...@@ -2305,9 +2317,10 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -2305,9 +2317,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ bind(&call); __ bind(&call);
} }
// The receiver is either the global receiver or a JSObject found by // The receiver is either the global receiver or an object found
// LoadContextSlot. // by LoadContextSlot. That object could be the hole if the
EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); // receiver is implicitly the global object.
EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
} else if (fun->AsProperty() != NULL) { } else if (fun->AsProperty() != NULL) {
// Call to an object property. // Call to an object property.
Property* prop = fun->AsProperty(); Property* prop = fun->AsProperty();
...@@ -2348,7 +2361,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { ...@@ -2348,7 +2361,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
{ PreservePositionScope scope(masm()->positions_recorder()); { PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
} }
EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); EmitKeyedCallWithIC(expr, prop->key());
} }
} }
} else { } else {
...@@ -3663,9 +3676,12 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -3663,9 +3676,12 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
if (expr->is_jsruntime()) { if (expr->is_jsruntime()) {
// Call the JS runtime function. // Call the JS runtime function.
__ li(a2, Operand(expr->name())); __ li(a2, Operand(expr->name()));
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); isolate()->stub_cache()->ComputeCallInitialize(arg_count,
EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); NOT_IN_LOOP,
mode);
EmitCallIC(ic, mode, expr->id());
// Restore context register. // Restore context register.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
} else { } else {
......
...@@ -494,7 +494,8 @@ Object* CallIC_Miss(Arguments args); ...@@ -494,7 +494,8 @@ Object* CallIC_Miss(Arguments args);
// The generated code falls through if both probes miss. // The generated code falls through if both probes miss.
static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
int argc, int argc,
Code::Kind kind) { Code::Kind kind,
Code::ExtraICState extra_ic_state) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a1 : receiver // -- a1 : receiver
// -- a2 : name // -- a2 : name
...@@ -505,7 +506,7 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, ...@@ -505,7 +506,7 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
Code::Flags flags = Code::ComputeFlags(kind, Code::Flags flags = Code::ComputeFlags(kind,
NOT_IN_LOOP, NOT_IN_LOOP,
MONOMORPHIC, MONOMORPHIC,
Code::kNoExtraICState, extra_ic_state,
NORMAL, NORMAL,
argc); argc);
Isolate::Current()->stub_cache()->GenerateProbe( Isolate::Current()->stub_cache()->GenerateProbe(
...@@ -593,7 +594,10 @@ static void GenerateCallNormal(MacroAssembler* masm, int argc) { ...@@ -593,7 +594,10 @@ static void GenerateCallNormal(MacroAssembler* masm, int argc) {
} }
static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { static void GenerateCallMiss(MacroAssembler* masm,
int argc,
IC::UtilityId id,
Code::ExtraICState extra_ic_state) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a2 : name // -- a2 : name
// -- ra : return address // -- ra : return address
...@@ -643,22 +647,33 @@ static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { ...@@ -643,22 +647,33 @@ static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
__ bind(&invoke); __ bind(&invoke);
} }
// Invoke the function. // Invoke the function.
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
ParameterCount actual(argc); ParameterCount actual(argc);
__ InvokeFunction(a1, actual, JUMP_FUNCTION); __ InvokeFunction(a1,
actual,
JUMP_FUNCTION,
NullCallWrapper(),
call_kind);
} }
void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { void CallIC::GenerateMiss(MacroAssembler* masm,
int argc,
Code::ExtraICState extra_ic_state) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a2 : name // -- a2 : name
// -- ra : return address // -- ra : return address
// ----------------------------------- // -----------------------------------
GenerateCallMiss(masm, argc, IC::kCallIC_Miss); GenerateCallMiss(masm, argc, IC::kCallIC_Miss, extra_ic_state);
} }
void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { void CallIC::GenerateMegamorphic(MacroAssembler* masm,
int argc,
Code::ExtraICState extra_ic_state) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a2 : name // -- a2 : name
// -- ra : return address // -- ra : return address
...@@ -666,8 +681,8 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { ...@@ -666,8 +681,8 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// Get the receiver of the function from the stack into a1. // Get the receiver of the function from the stack into a1.
__ lw(a1, MemOperand(sp, argc * kPointerSize)); __ lw(a1, MemOperand(sp, argc * kPointerSize));
GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC); GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state);
GenerateMiss(masm, argc); GenerateMiss(masm, argc, extra_ic_state);
} }
...@@ -678,7 +693,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { ...@@ -678,7 +693,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
// ----------------------------------- // -----------------------------------
GenerateCallNormal(masm, argc); GenerateCallNormal(masm, argc);
GenerateMiss(masm, argc); GenerateMiss(masm, argc, Code::kNoExtraICState);
} }
...@@ -688,7 +703,7 @@ void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { ...@@ -688,7 +703,7 @@ void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
// -- ra : return address // -- ra : return address
// ----------------------------------- // -----------------------------------
GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState);
} }
...@@ -773,7 +788,10 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { ...@@ -773,7 +788,10 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
__ bind(&lookup_monomorphic_cache); __ bind(&lookup_monomorphic_cache);
__ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, a0, a3); __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, a0, a3);
GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); GenerateMonomorphicCacheProbe(masm,
argc,
Code::KEYED_CALL_IC,
Code::kNoExtraICState);
// Fall through on miss. // Fall through on miss.
__ bind(&slow_call); __ bind(&slow_call);
......
...@@ -2699,6 +2699,21 @@ void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg, ...@@ -2699,6 +2699,21 @@ void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
} }
} }
void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
// This macro takes the dst register to make the code more readable
// at the call sites. However, the dst register has to be t1 to
// follow the calling convention which requires the call type to be
// in t1.
ASSERT(dst.is(t1));
if (call_kind == CALL_AS_FUNCTION) {
li(dst, Operand(Smi::FromInt(1)));
} else {
li(dst, Operand(Smi::FromInt(0)));
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// JavaScript invokes. // JavaScript invokes.
...@@ -2708,7 +2723,8 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, ...@@ -2708,7 +2723,8 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Register code_reg, Register code_reg,
Label* done, Label* done,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper) { const CallWrapper& call_wrapper,
CallKind call_kind) {
bool definitely_matches = false; bool definitely_matches = false;
Label regular_invoke; Label regular_invoke;
...@@ -2760,10 +2776,12 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, ...@@ -2760,10 +2776,12 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
isolate()->builtins()->ArgumentsAdaptorTrampoline(); isolate()->builtins()->ArgumentsAdaptorTrampoline();
if (flag == CALL_FUNCTION) { if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET));
SetCallKind(t1, call_kind);
Call(adaptor, RelocInfo::CODE_TARGET); Call(adaptor, RelocInfo::CODE_TARGET);
call_wrapper.AfterCall(); call_wrapper.AfterCall();
jmp(done); jmp(done);
} else { } else {
SetCallKind(t1, call_kind);
Jump(adaptor, RelocInfo::CODE_TARGET); Jump(adaptor, RelocInfo::CODE_TARGET);
} }
bind(&regular_invoke); bind(&regular_invoke);
...@@ -2775,15 +2793,18 @@ void MacroAssembler::InvokeCode(Register code, ...@@ -2775,15 +2793,18 @@ void MacroAssembler::InvokeCode(Register code,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper) { const CallWrapper& call_wrapper,
CallKind call_kind) {
Label done; Label done;
InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
call_wrapper); call_wrapper, call_kind);
if (flag == CALL_FUNCTION) { if (flag == CALL_FUNCTION) {
SetCallKind(t1, call_kind);
Call(code); Call(code);
} else { } else {
ASSERT(flag == JUMP_FUNCTION); ASSERT(flag == JUMP_FUNCTION);
SetCallKind(t1, call_kind);
Jump(code); Jump(code);
} }
// Continue here if InvokePrologue does handle the invocation due to // Continue here if InvokePrologue does handle the invocation due to
...@@ -2796,13 +2817,17 @@ void MacroAssembler::InvokeCode(Handle<Code> code, ...@@ -2796,13 +2817,17 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
RelocInfo::Mode rmode, RelocInfo::Mode rmode,
InvokeFlag flag) { InvokeFlag flag,
CallKind call_kind) {
Label done; Label done;
InvokePrologue(expected, actual, code, no_reg, &done, flag); InvokePrologue(expected, actual, code, no_reg, &done, flag,
NullCallWrapper(), call_kind);
if (flag == CALL_FUNCTION) { if (flag == CALL_FUNCTION) {
SetCallKind(t1, call_kind);
Call(code, rmode); Call(code, rmode);
} else { } else {
SetCallKind(t1, call_kind);
Jump(code, rmode); Jump(code, rmode);
} }
// Continue here if InvokePrologue does handle the invocation due to // Continue here if InvokePrologue does handle the invocation due to
...@@ -2814,7 +2839,8 @@ void MacroAssembler::InvokeCode(Handle<Code> code, ...@@ -2814,7 +2839,8 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
void MacroAssembler::InvokeFunction(Register function, void MacroAssembler::InvokeFunction(Register function,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper) { const CallWrapper& call_wrapper,
CallKind call_kind) {
// Contract with called JS functions requires that function is passed in a1. // Contract with called JS functions requires that function is passed in a1.
ASSERT(function.is(a1)); ASSERT(function.is(a1));
Register expected_reg = a2; Register expected_reg = a2;
...@@ -2829,7 +2855,7 @@ void MacroAssembler::InvokeFunction(Register function, ...@@ -2829,7 +2855,7 @@ void MacroAssembler::InvokeFunction(Register function,
lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
ParameterCount expected(expected_reg); ParameterCount expected(expected_reg);
InvokeCode(code_reg, expected, actual, flag, call_wrapper); InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind);
} }
......
...@@ -614,25 +614,33 @@ DECLARE_NOTARGET_PROTOTYPE(Ret) ...@@ -614,25 +614,33 @@ DECLARE_NOTARGET_PROTOTYPE(Ret)
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// JavaScript invokes. // JavaScript invokes.
// Setup call kind marking in t1. The method takes t1 as an
// explicit first parameter to make the code more readable at the
// call sites.
void SetCallKind(Register dst, CallKind kind);
// Invoke the JavaScript function code by either calling or jumping. // Invoke the JavaScript function code by either calling or jumping.
void InvokeCode(Register code, void InvokeCode(Register code,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper()); const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
void InvokeCode(Handle<Code> code, void InvokeCode(Handle<Code> code,
const ParameterCount& expected, const ParameterCount& expected,
const ParameterCount& actual, const ParameterCount& actual,
RelocInfo::Mode rmode, RelocInfo::Mode rmode,
InvokeFlag flag); InvokeFlag flag,
CallKind call_kind = CALL_AS_METHOD);
// Invoke the JavaScript function in the given register. Changes the // Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking. // current context to the context in the function before invoking.
void InvokeFunction(Register function, void InvokeFunction(Register function,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper()); const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
void InvokeFunction(JSFunction* function, void InvokeFunction(JSFunction* function,
const ParameterCount& actual, const ParameterCount& actual,
...@@ -1098,7 +1106,8 @@ DECLARE_NOTARGET_PROTOTYPE(Ret) ...@@ -1098,7 +1106,8 @@ DECLARE_NOTARGET_PROTOTYPE(Ret)
Register code_reg, Register code_reg,
Label* done, Label* done,
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper()); const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
// Get the code for the given builtin. Returns if able to resolve // Get the code for the given builtin. Returns if able to resolve
// the function in the 'resolved' flag. // the function in the 'resolved' flag.
......
...@@ -1469,8 +1469,10 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, ...@@ -1469,8 +1469,10 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
MaybeObject* CallStubCompiler::GenerateMissBranch() { MaybeObject* CallStubCompiler::GenerateMissBranch() {
MaybeObject* maybe_obj = masm()->isolate()->stub_cache()->ComputeCallMiss( MaybeObject* maybe_obj =
arguments().immediate(), kind_); isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
kind_,
extra_ic_state_);
Object* obj; Object* obj;
if (!maybe_obj->ToObject(&obj)) return maybe_obj; if (!maybe_obj->ToObject(&obj)) return maybe_obj;
__ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
...@@ -1789,7 +1791,9 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( ...@@ -1789,7 +1791,9 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
Label* index_out_of_range_label = &index_out_of_range; Label* index_out_of_range_label = &index_out_of_range;
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { if (kind_ == Code::CALL_IC &&
(CallICBase::StringStubState::decode(extra_ic_state_) ==
DEFAULT_STRING_STUB)) {
index_out_of_range_label = &miss; index_out_of_range_label = &miss;
} }
...@@ -1873,7 +1877,9 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall( ...@@ -1873,7 +1877,9 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
Label index_out_of_range; Label index_out_of_range;
Label* index_out_of_range_label = &index_out_of_range; Label* index_out_of_range_label = &index_out_of_range;
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { if (kind_ == Code::CALL_IC &&
(CallICBase::StringStubState::decode(extra_ic_state_) ==
DEFAULT_STRING_STUB)) {
index_out_of_range_label = &miss; index_out_of_range_label = &miss;
} }
...@@ -2485,11 +2491,13 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, ...@@ -2485,11 +2491,13 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
} }
MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, MaybeObject* CallStubCompiler::CompileCallGlobal(
GlobalObject* holder, JSObject* object,
JSGlobalPropertyCell* cell, GlobalObject* holder,
JSFunction* function, JSGlobalPropertyCell* cell,
String* name) { JSFunction* function,
String* name,
Code::ExtraICState extra_ic_state) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a2 : name // -- a2 : name
// -- ra : return address // -- ra : return address
...@@ -2530,11 +2538,14 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, ...@@ -2530,11 +2538,14 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
ASSERT(function->is_compiled()); ASSERT(function->is_compiled());
Handle<Code> code(function->code()); Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count()); ParameterCount expected(function->shared()->formal_parameter_count());
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
if (V8::UseCrankshaft()) { if (V8::UseCrankshaft()) {
UNIMPLEMENTED_MIPS(); UNIMPLEMENTED_MIPS();
} else { } else {
__ InvokeCode(code, expected, arguments(), __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET,
RelocInfo::CODE_TARGET, JUMP_FUNCTION); JUMP_FUNCTION, call_kind);
} }
// Handle call cache miss. // Handle call cache miss.
......
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