OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 __ stop("stop_at"); | 140 __ stop("stop_at"); |
141 } | 141 } |
142 #endif | 142 #endif |
143 | 143 |
144 // r1: Callee's JS function. | 144 // r1: Callee's JS function. |
145 // cp: Callee's context. | 145 // cp: Callee's context. |
146 // pp: Callee's constant pool pointer (if FLAG_enable_ool_constant_pool) | 146 // pp: Callee's constant pool pointer (if FLAG_enable_ool_constant_pool) |
147 // fp: Caller's frame pointer. | 147 // fp: Caller's frame pointer. |
148 // lr: Caller's pc. | 148 // lr: Caller's pc. |
149 | 149 |
150 // Strict mode functions and builtins need to replace the receiver | 150 // Classic mode functions and builtins need to replace the receiver with the |
151 // with undefined when called as functions (without an explicit | 151 // global proxy when called as functions (without an explicit receiver |
152 // receiver object). r5 is zero for method calls and non-zero for | 152 // object). |
153 // function calls. | 153 if (info_->this_has_uses() && |
154 if (!info_->is_classic_mode() || info_->is_native()) { | 154 info_->is_classic_mode() && |
| 155 !info_->is_native()) { |
| 156 Label ok; |
155 __ cmp(r5, Operand::Zero()); | 157 __ cmp(r5, Operand::Zero()); |
156 int receiver_offset = scope()->num_parameters() * kPointerSize; | 158 __ b(eq, &ok); |
157 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 159 |
158 __ str(r2, MemOperand(sp, receiver_offset), ne); | 160 int receiver_offset = info_->scope()->num_parameters() * kPointerSize; |
| 161 __ ldr(r2, MemOperand(sp, receiver_offset)); |
| 162 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 163 __ b(ne, &ok); |
| 164 |
| 165 __ ldr(r2, GlobalObjectOperand()); |
| 166 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); |
| 167 |
| 168 __ str(r2, MemOperand(sp, receiver_offset)); |
| 169 |
| 170 __ bind(&ok); |
159 } | 171 } |
160 } | 172 } |
161 | 173 |
162 info()->set_prologue_offset(masm_->pc_offset()); | 174 info()->set_prologue_offset(masm_->pc_offset()); |
163 if (NeedsEagerFrame()) { | 175 if (NeedsEagerFrame()) { |
164 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); | 176 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
165 frame_is_built_ = true; | 177 frame_is_built_ = true; |
166 info_->AddNoFrameRange(0, masm_->pc_offset()); | 178 info_->AddNoFrameRange(0, masm_->pc_offset()); |
167 __ LoadConstantPoolPointerRegister(); | 179 __ LoadConstantPoolPointerRegister(); |
168 } | 180 } |
(...skipping 3318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3487 __ b(eq, &global_object); | 3499 __ b(eq, &global_object); |
3488 | 3500 |
3489 // Deoptimize if the receiver is not a JS object. | 3501 // Deoptimize if the receiver is not a JS object. |
3490 __ SmiTst(receiver); | 3502 __ SmiTst(receiver); |
3491 DeoptimizeIf(eq, instr->environment()); | 3503 DeoptimizeIf(eq, instr->environment()); |
3492 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); | 3504 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); |
3493 DeoptimizeIf(lt, instr->environment()); | 3505 DeoptimizeIf(lt, instr->environment()); |
3494 __ b(&result_in_receiver); | 3506 __ b(&result_in_receiver); |
3495 | 3507 |
3496 __ bind(&global_object); | 3508 __ bind(&global_object); |
3497 CallStubCompiler::FetchGlobalProxy(masm(), receiver, function); | 3509 __ ldr(receiver, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3510 __ ldr(receiver, |
| 3511 ContextOperand(receiver, |
| 3512 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 3513 __ ldr(receiver, |
| 3514 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
3498 | 3515 |
3499 if (result.is(receiver)) { | 3516 if (result.is(receiver)) { |
3500 __ bind(&result_in_receiver); | 3517 __ bind(&result_in_receiver); |
3501 } else { | 3518 } else { |
3502 Label result_ok; | 3519 Label result_ok; |
3503 __ b(&result_ok); | 3520 __ b(&result_ok); |
3504 __ bind(&result_in_receiver); | 3521 __ bind(&result_in_receiver); |
3505 __ mov(result, receiver); | 3522 __ mov(result, receiver); |
3506 __ bind(&result_ok); | 3523 __ bind(&result_ok); |
3507 } | 3524 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3545 | 3562 |
3546 __ bind(&invoke); | 3563 __ bind(&invoke); |
3547 ASSERT(instr->HasPointerMap()); | 3564 ASSERT(instr->HasPointerMap()); |
3548 LPointerMap* pointers = instr->pointer_map(); | 3565 LPointerMap* pointers = instr->pointer_map(); |
3549 SafepointGenerator safepoint_generator( | 3566 SafepointGenerator safepoint_generator( |
3550 this, pointers, Safepoint::kLazyDeopt); | 3567 this, pointers, Safepoint::kLazyDeopt); |
3551 // The number of arguments is stored in receiver which is r0, as expected | 3568 // The number of arguments is stored in receiver which is r0, as expected |
3552 // by InvokeFunction. | 3569 // by InvokeFunction. |
3553 ParameterCount actual(receiver); | 3570 ParameterCount actual(receiver); |
3554 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3571 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3555 safepoint_generator, CALL_AS_METHOD); | 3572 safepoint_generator, CALL_AS_FUNCTION); |
3556 } | 3573 } |
3557 | 3574 |
3558 | 3575 |
3559 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3576 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3560 LOperand* argument = instr->value(); | 3577 LOperand* argument = instr->value(); |
3561 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3578 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
3562 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3579 Abort(kDoPushArgumentNotImplementedForDoubleType); |
3563 } else { | 3580 } else { |
3564 Register argument_reg = EmitLoadRegister(argument, ip); | 3581 Register argument_reg = EmitLoadRegister(argument, ip); |
3565 __ push(argument_reg); | 3582 __ push(argument_reg); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3666 } | 3683 } |
3667 } | 3684 } |
3668 | 3685 |
3669 | 3686 |
3670 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3687 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
3671 ASSERT(ToRegister(instr->result()).is(r0)); | 3688 ASSERT(ToRegister(instr->result()).is(r0)); |
3672 CallKnownFunction(instr->hydrogen()->function(), | 3689 CallKnownFunction(instr->hydrogen()->function(), |
3673 instr->hydrogen()->formal_parameter_count(), | 3690 instr->hydrogen()->formal_parameter_count(), |
3674 instr->arity(), | 3691 instr->arity(), |
3675 instr, | 3692 instr, |
3676 CALL_AS_METHOD, | 3693 CALL_AS_FUNCTION, |
3677 R1_UNINITIALIZED); | 3694 R1_UNINITIALIZED); |
3678 } | 3695 } |
3679 | 3696 |
3680 | 3697 |
3681 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3698 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
3682 ASSERT(instr->context() != NULL); | 3699 ASSERT(instr->context() != NULL); |
3683 ASSERT(ToRegister(instr->context()).is(cp)); | 3700 ASSERT(ToRegister(instr->context()).is(cp)); |
3684 Register input = ToRegister(instr->value()); | 3701 Register input = ToRegister(instr->value()); |
3685 Register result = ToRegister(instr->result()); | 3702 Register result = ToRegister(instr->result()); |
3686 Register scratch = scratch0(); | 3703 Register scratch = scratch0(); |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3944 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3961 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
3945 ASSERT(ToRegister(instr->context()).is(cp)); | 3962 ASSERT(ToRegister(instr->context()).is(cp)); |
3946 ASSERT(ToRegister(instr->function()).is(r1)); | 3963 ASSERT(ToRegister(instr->function()).is(r1)); |
3947 ASSERT(instr->HasPointerMap()); | 3964 ASSERT(instr->HasPointerMap()); |
3948 | 3965 |
3949 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3966 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
3950 if (known_function.is_null()) { | 3967 if (known_function.is_null()) { |
3951 LPointerMap* pointers = instr->pointer_map(); | 3968 LPointerMap* pointers = instr->pointer_map(); |
3952 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3969 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3953 ParameterCount count(instr->arity()); | 3970 ParameterCount count(instr->arity()); |
3954 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3971 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); |
3955 } else { | 3972 } else { |
3956 CallKnownFunction(known_function, | 3973 CallKnownFunction(known_function, |
3957 instr->hydrogen()->formal_parameter_count(), | 3974 instr->hydrogen()->formal_parameter_count(), |
3958 instr->arity(), | 3975 instr->arity(), |
3959 instr, | 3976 instr, |
3960 CALL_AS_METHOD, | 3977 CALL_AS_FUNCTION, |
3961 R1_CONTAINS_TARGET); | 3978 R1_CONTAINS_TARGET); |
3962 } | 3979 } |
3963 } | 3980 } |
3964 | 3981 |
3965 | 3982 |
3966 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 3983 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
3967 ASSERT(ToRegister(instr->context()).is(cp)); | 3984 ASSERT(ToRegister(instr->context()).is(cp)); |
3968 ASSERT(ToRegister(instr->result()).is(r0)); | 3985 ASSERT(ToRegister(instr->result()).is(r0)); |
3969 | 3986 |
3970 int arity = instr->arity(); | 3987 int arity = instr->arity(); |
(...skipping 14 matching lines...) Expand all Loading... |
3985 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4002 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
3986 } | 4003 } |
3987 | 4004 |
3988 | 4005 |
3989 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4006 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
3990 ASSERT(ToRegister(instr->context()).is(cp)); | 4007 ASSERT(ToRegister(instr->context()).is(cp)); |
3991 ASSERT(ToRegister(instr->function()).is(r1)); | 4008 ASSERT(ToRegister(instr->function()).is(r1)); |
3992 ASSERT(ToRegister(instr->result()).is(r0)); | 4009 ASSERT(ToRegister(instr->result()).is(r0)); |
3993 | 4010 |
3994 int arity = instr->arity(); | 4011 int arity = instr->arity(); |
3995 CallFunctionFlags flags = | 4012 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
3996 instr->hydrogen()->IsContextualCall() ? | |
3997 RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS; | |
3998 CallFunctionStub stub(arity, flags); | |
3999 if (instr->hydrogen()->IsTailCall()) { | 4013 if (instr->hydrogen()->IsTailCall()) { |
4000 if (NeedsEagerFrame()) __ mov(sp, fp); | 4014 if (NeedsEagerFrame()) __ mov(sp, fp); |
4001 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 4015 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
4002 } else { | 4016 } else { |
4003 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4017 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
4004 } | 4018 } |
4005 } | 4019 } |
4006 | 4020 |
4007 | 4021 |
4008 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4022 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
(...skipping 1801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5810 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5824 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5811 __ ldr(result, FieldMemOperand(scratch, | 5825 __ ldr(result, FieldMemOperand(scratch, |
5812 FixedArray::kHeaderSize - kPointerSize)); | 5826 FixedArray::kHeaderSize - kPointerSize)); |
5813 __ bind(&done); | 5827 __ bind(&done); |
5814 } | 5828 } |
5815 | 5829 |
5816 | 5830 |
5817 #undef __ | 5831 #undef __ |
5818 | 5832 |
5819 } } // namespace v8::internal | 5833 } } // namespace v8::internal |
OLD | NEW |