OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 if (info()->IsOptimizing()) { | 149 if (info()->IsOptimizing()) { |
150 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 150 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
151 | 151 |
152 #ifdef DEBUG | 152 #ifdef DEBUG |
153 if (strlen(FLAG_stop_at) > 0 && | 153 if (strlen(FLAG_stop_at) > 0 && |
154 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 154 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
155 __ int3(); | 155 __ int3(); |
156 } | 156 } |
157 #endif | 157 #endif |
158 | 158 |
159 // Strict mode functions need to replace the receiver with undefined | 159 // Classic mode functions need to replace the receiver with the global proxy |
160 // when called as functions (without an explicit receiver | 160 // when called as functions (without an explicit receiver object). |
161 // object). rcx is zero for method calls and non-zero for function | 161 if (info_->this_has_uses() && |
162 // calls. | 162 info_->is_classic_mode() && |
163 if (!info_->is_classic_mode() || info_->is_native()) { | 163 !info_->is_native()) { |
164 Label ok; | 164 Label ok; |
165 __ testq(rcx, rcx); | 165 __ testq(rcx, rcx); |
166 __ j(zero, &ok, Label::kNear); | 166 __ j(zero, &ok, Label::kNear); |
| 167 |
167 StackArgumentsAccessor args(rsp, scope()->num_parameters()); | 168 StackArgumentsAccessor args(rsp, scope()->num_parameters()); |
168 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 169 __ movq(rcx, args.GetReceiverOperand()); |
169 __ movq(args.GetReceiverOperand(), kScratchRegister); | 170 |
| 171 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); |
| 172 __ j(not_equal, &ok, Label::kNear); |
| 173 |
| 174 __ movq(rcx, GlobalObjectOperand()); |
| 175 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
| 176 |
| 177 __ movq(args.GetReceiverOperand(), rcx); |
| 178 |
170 __ bind(&ok); | 179 __ bind(&ok); |
171 } | 180 } |
172 } | 181 } |
173 | 182 |
174 info()->set_prologue_offset(masm_->pc_offset()); | 183 info()->set_prologue_offset(masm_->pc_offset()); |
175 if (NeedsEagerFrame()) { | 184 if (NeedsEagerFrame()) { |
176 ASSERT(!frame_is_built_); | 185 ASSERT(!frame_is_built_); |
177 frame_is_built_ = true; | 186 frame_is_built_ = true; |
178 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); | 187 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
179 info()->AddNoFrameRange(0, masm_->pc_offset()); | 188 info()->AddNoFrameRange(0, masm_->pc_offset()); |
(...skipping 3059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3239 __ j(equal, &global_object, Label::kNear); | 3248 __ j(equal, &global_object, Label::kNear); |
3240 | 3249 |
3241 // The receiver should be a JS object. | 3250 // The receiver should be a JS object. |
3242 Condition is_smi = __ CheckSmi(receiver); | 3251 Condition is_smi = __ CheckSmi(receiver); |
3243 DeoptimizeIf(is_smi, instr->environment()); | 3252 DeoptimizeIf(is_smi, instr->environment()); |
3244 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); | 3253 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
3245 DeoptimizeIf(below, instr->environment()); | 3254 DeoptimizeIf(below, instr->environment()); |
3246 __ jmp(&receiver_ok, Label::kNear); | 3255 __ jmp(&receiver_ok, Label::kNear); |
3247 | 3256 |
3248 __ bind(&global_object); | 3257 __ bind(&global_object); |
3249 // TODO(kmillikin): We have a hydrogen value for the global object. See | 3258 __ movq(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
3250 // if it's better to use it than to explicitly fetch it from the context | 3259 __ movq(receiver, |
3251 // here. | 3260 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
3252 CallStubCompiler::FetchGlobalProxy(masm(), receiver, function); | 3261 __ movq(receiver, |
| 3262 FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
3253 __ bind(&receiver_ok); | 3263 __ bind(&receiver_ok); |
3254 } | 3264 } |
3255 | 3265 |
3256 | 3266 |
3257 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3267 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
3258 Register receiver = ToRegister(instr->receiver()); | 3268 Register receiver = ToRegister(instr->receiver()); |
3259 Register function = ToRegister(instr->function()); | 3269 Register function = ToRegister(instr->function()); |
3260 Register length = ToRegister(instr->length()); | 3270 Register length = ToRegister(instr->length()); |
3261 Register elements = ToRegister(instr->elements()); | 3271 Register elements = ToRegister(instr->elements()); |
3262 ASSERT(receiver.is(rax)); // Used for parameter count. | 3272 ASSERT(receiver.is(rax)); // Used for parameter count. |
(...skipping 23 matching lines...) Expand all Loading... |
3286 __ j(not_zero, &loop); | 3296 __ j(not_zero, &loop); |
3287 | 3297 |
3288 // Invoke the function. | 3298 // Invoke the function. |
3289 __ bind(&invoke); | 3299 __ bind(&invoke); |
3290 ASSERT(instr->HasPointerMap()); | 3300 ASSERT(instr->HasPointerMap()); |
3291 LPointerMap* pointers = instr->pointer_map(); | 3301 LPointerMap* pointers = instr->pointer_map(); |
3292 SafepointGenerator safepoint_generator( | 3302 SafepointGenerator safepoint_generator( |
3293 this, pointers, Safepoint::kLazyDeopt); | 3303 this, pointers, Safepoint::kLazyDeopt); |
3294 ParameterCount actual(rax); | 3304 ParameterCount actual(rax); |
3295 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3305 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3296 safepoint_generator, CALL_AS_METHOD); | 3306 safepoint_generator, CALL_AS_FUNCTION); |
3297 } | 3307 } |
3298 | 3308 |
3299 | 3309 |
3300 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3310 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3301 LOperand* argument = instr->value(); | 3311 LOperand* argument = instr->value(); |
3302 EmitPushTaggedOperand(argument); | 3312 EmitPushTaggedOperand(argument); |
3303 } | 3313 } |
3304 | 3314 |
3305 | 3315 |
3306 void LCodeGen::DoDrop(LDrop* instr) { | 3316 void LCodeGen::DoDrop(LDrop* instr) { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3405 } | 3415 } |
3406 } | 3416 } |
3407 | 3417 |
3408 | 3418 |
3409 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3419 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
3410 ASSERT(ToRegister(instr->result()).is(rax)); | 3420 ASSERT(ToRegister(instr->result()).is(rax)); |
3411 CallKnownFunction(instr->hydrogen()->function(), | 3421 CallKnownFunction(instr->hydrogen()->function(), |
3412 instr->hydrogen()->formal_parameter_count(), | 3422 instr->hydrogen()->formal_parameter_count(), |
3413 instr->arity(), | 3423 instr->arity(), |
3414 instr, | 3424 instr, |
3415 CALL_AS_METHOD, | 3425 CALL_AS_FUNCTION, |
3416 RDI_UNINITIALIZED); | 3426 RDI_UNINITIALIZED); |
3417 } | 3427 } |
3418 | 3428 |
3419 | 3429 |
3420 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3430 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
3421 Register input_reg = ToRegister(instr->value()); | 3431 Register input_reg = ToRegister(instr->value()); |
3422 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3432 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
3423 Heap::kHeapNumberMapRootIndex); | 3433 Heap::kHeapNumberMapRootIndex); |
3424 DeoptimizeIf(not_equal, instr->environment()); | 3434 DeoptimizeIf(not_equal, instr->environment()); |
3425 | 3435 |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3764 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3774 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
3765 ASSERT(ToRegister(instr->context()).is(rsi)); | 3775 ASSERT(ToRegister(instr->context()).is(rsi)); |
3766 ASSERT(ToRegister(instr->function()).is(rdi)); | 3776 ASSERT(ToRegister(instr->function()).is(rdi)); |
3767 ASSERT(instr->HasPointerMap()); | 3777 ASSERT(instr->HasPointerMap()); |
3768 | 3778 |
3769 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3779 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
3770 if (known_function.is_null()) { | 3780 if (known_function.is_null()) { |
3771 LPointerMap* pointers = instr->pointer_map(); | 3781 LPointerMap* pointers = instr->pointer_map(); |
3772 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3782 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3773 ParameterCount count(instr->arity()); | 3783 ParameterCount count(instr->arity()); |
3774 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3784 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); |
3775 } else { | 3785 } else { |
3776 CallKnownFunction(known_function, | 3786 CallKnownFunction(known_function, |
3777 instr->hydrogen()->formal_parameter_count(), | 3787 instr->hydrogen()->formal_parameter_count(), |
3778 instr->arity(), | 3788 instr->arity(), |
3779 instr, | 3789 instr, |
3780 CALL_AS_METHOD, | 3790 CALL_AS_FUNCTION, |
3781 RDI_CONTAINS_TARGET); | 3791 RDI_CONTAINS_TARGET); |
3782 } | 3792 } |
3783 } | 3793 } |
3784 | 3794 |
3785 | 3795 |
3786 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 3796 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
3787 ASSERT(ToRegister(instr->context()).is(rsi)); | 3797 ASSERT(ToRegister(instr->context()).is(rsi)); |
3788 ASSERT(ToRegister(instr->key()).is(rcx)); | 3798 ASSERT(ToRegister(instr->key()).is(rcx)); |
3789 ASSERT(ToRegister(instr->result()).is(rax)); | 3799 ASSERT(ToRegister(instr->result()).is(rax)); |
3790 | 3800 |
(...skipping 15 matching lines...) Expand all Loading... |
3806 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3816 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3807 } | 3817 } |
3808 | 3818 |
3809 | 3819 |
3810 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3820 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
3811 ASSERT(ToRegister(instr->context()).is(rsi)); | 3821 ASSERT(ToRegister(instr->context()).is(rsi)); |
3812 ASSERT(ToRegister(instr->function()).is(rdi)); | 3822 ASSERT(ToRegister(instr->function()).is(rdi)); |
3813 ASSERT(ToRegister(instr->result()).is(rax)); | 3823 ASSERT(ToRegister(instr->result()).is(rax)); |
3814 | 3824 |
3815 int arity = instr->arity(); | 3825 int arity = instr->arity(); |
3816 CallFunctionFlags flags = | 3826 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
3817 instr->hydrogen()->IsContextualCall() ? | |
3818 RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS; | |
3819 CallFunctionStub stub(arity, flags); | |
3820 if (instr->hydrogen()->IsTailCall()) { | 3827 if (instr->hydrogen()->IsTailCall()) { |
3821 if (NeedsEagerFrame()) __ leave(); | 3828 if (NeedsEagerFrame()) __ leave(); |
3822 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 3829 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
3823 } else { | 3830 } else { |
3824 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3831 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
3825 } | 3832 } |
3826 } | 3833 } |
3827 | 3834 |
3828 | 3835 |
3829 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 3836 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
(...skipping 1799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5629 FixedArray::kHeaderSize - kPointerSize)); | 5636 FixedArray::kHeaderSize - kPointerSize)); |
5630 __ bind(&done); | 5637 __ bind(&done); |
5631 } | 5638 } |
5632 | 5639 |
5633 | 5640 |
5634 #undef __ | 5641 #undef __ |
5635 | 5642 |
5636 } } // namespace v8::internal | 5643 } } // namespace v8::internal |
5637 | 5644 |
5638 #endif // V8_TARGET_ARCH_X64 | 5645 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |