| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 class SafepointGenerator V8_FINAL : public CallWrapper { | 43 class SafepointGenerator V8_FINAL : public CallWrapper { |
| 44 public: | 44 public: |
| 45 SafepointGenerator(LCodeGen* codegen, | 45 SafepointGenerator(LCodeGen* codegen, |
| 46 LPointerMap* pointers, | 46 LPointerMap* pointers, |
| 47 Safepoint::DeoptMode mode) | 47 Safepoint::DeoptMode mode) |
| 48 : codegen_(codegen), | 48 : codegen_(codegen), |
| 49 pointers_(pointers), | 49 pointers_(pointers), |
| 50 deopt_mode_(mode) { } | 50 deopt_mode_(mode) { } |
| 51 virtual ~SafepointGenerator() {} | 51 virtual ~SafepointGenerator() {} |
| 52 | 52 |
| 53 virtual void BeforeCall(int call_size) const V8_OVERRIDE { | 53 virtual void BeforeCall(int call_size) const V8_OVERRIDE {} |
| 54 codegen_->EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - call_size); | |
| 55 } | |
| 56 | 54 |
| 57 virtual void AfterCall() const V8_OVERRIDE { | 55 virtual void AfterCall() const V8_OVERRIDE { |
| 58 codegen_->RecordSafepoint(pointers_, deopt_mode_); | 56 codegen_->RecordSafepoint(pointers_, deopt_mode_); |
| 59 } | 57 } |
| 60 | 58 |
| 61 private: | 59 private: |
| 62 LCodeGen* codegen_; | 60 LCodeGen* codegen_; |
| 63 LPointerMap* pointers_; | 61 LPointerMap* pointers_; |
| 64 Safepoint::DeoptMode deopt_mode_; | 62 Safepoint::DeoptMode deopt_mode_; |
| 65 }; | 63 }; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 __ int3(); | 153 __ int3(); |
| 156 } | 154 } |
| 157 #endif | 155 #endif |
| 158 | 156 |
| 159 // Classic mode functions need to replace the receiver with the global proxy | 157 // Classic mode functions need to replace the receiver with the global proxy |
| 160 // when called as functions (without an explicit receiver object). | 158 // when called as functions (without an explicit receiver object). |
| 161 if (info_->this_has_uses() && | 159 if (info_->this_has_uses() && |
| 162 info_->is_classic_mode() && | 160 info_->is_classic_mode() && |
| 163 !info_->is_native()) { | 161 !info_->is_native()) { |
| 164 Label ok; | 162 Label ok; |
| 165 __ testq(rcx, rcx); | |
| 166 __ j(zero, &ok, Label::kNear); | |
| 167 | |
| 168 StackArgumentsAccessor args(rsp, scope()->num_parameters()); | 163 StackArgumentsAccessor args(rsp, scope()->num_parameters()); |
| 169 __ movq(rcx, args.GetReceiverOperand()); | 164 __ movq(rcx, args.GetReceiverOperand()); |
| 170 | 165 |
| 171 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); | 166 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); |
| 172 __ j(not_equal, &ok, Label::kNear); | 167 __ j(not_equal, &ok, Label::kNear); |
| 173 | 168 |
| 174 __ movq(rcx, GlobalObjectOperand()); | 169 __ movq(rcx, GlobalObjectOperand()); |
| 175 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); | 170 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
| 176 | 171 |
| 177 __ movq(args.GetReceiverOperand(), rcx); | 172 __ movq(args.GetReceiverOperand(), rcx); |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 UNREACHABLE(); | 593 UNREACHABLE(); |
| 599 } | 594 } |
| 600 } | 595 } |
| 601 | 596 |
| 602 | 597 |
| 603 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 598 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 604 RelocInfo::Mode mode, | 599 RelocInfo::Mode mode, |
| 605 LInstruction* instr, | 600 LInstruction* instr, |
| 606 SafepointMode safepoint_mode, | 601 SafepointMode safepoint_mode, |
| 607 int argc) { | 602 int argc) { |
| 608 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - masm()->CallSize(code)); | |
| 609 ASSERT(instr != NULL); | 603 ASSERT(instr != NULL); |
| 610 __ call(code, mode); | 604 __ call(code, mode); |
| 611 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); | 605 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); |
| 612 | 606 |
| 613 // Signal that we don't inline smi code before these stubs in the | 607 // Signal that we don't inline smi code before these stubs in the |
| 614 // optimizing code generator. | 608 // optimizing code generator. |
| 615 if (code->kind() == Code::BINARY_OP_IC || | 609 if (code->kind() == Code::BINARY_OP_IC || |
| 616 code->kind() == Code::COMPARE_IC) { | 610 code->kind() == Code::COMPARE_IC) { |
| 617 __ nop(); | 611 __ nop(); |
| 618 } | 612 } |
| (...skipping 2676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3295 __ decl(length); | 3289 __ decl(length); |
| 3296 __ j(not_zero, &loop); | 3290 __ j(not_zero, &loop); |
| 3297 | 3291 |
| 3298 // Invoke the function. | 3292 // Invoke the function. |
| 3299 __ bind(&invoke); | 3293 __ bind(&invoke); |
| 3300 ASSERT(instr->HasPointerMap()); | 3294 ASSERT(instr->HasPointerMap()); |
| 3301 LPointerMap* pointers = instr->pointer_map(); | 3295 LPointerMap* pointers = instr->pointer_map(); |
| 3302 SafepointGenerator safepoint_generator( | 3296 SafepointGenerator safepoint_generator( |
| 3303 this, pointers, Safepoint::kLazyDeopt); | 3297 this, pointers, Safepoint::kLazyDeopt); |
| 3304 ParameterCount actual(rax); | 3298 ParameterCount actual(rax); |
| 3305 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3299 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); |
| 3306 safepoint_generator, CALL_AS_FUNCTION); | |
| 3307 } | 3300 } |
| 3308 | 3301 |
| 3309 | 3302 |
| 3310 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3303 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3311 LOperand* argument = instr->value(); | 3304 LOperand* argument = instr->value(); |
| 3312 EmitPushTaggedOperand(argument); | 3305 EmitPushTaggedOperand(argument); |
| 3313 } | 3306 } |
| 3314 | 3307 |
| 3315 | 3308 |
| 3316 void LCodeGen::DoDrop(LDrop* instr) { | 3309 void LCodeGen::DoDrop(LDrop* instr) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3364 Register global = ToRegister(instr->global()); | 3357 Register global = ToRegister(instr->global()); |
| 3365 Register result = ToRegister(instr->result()); | 3358 Register result = ToRegister(instr->result()); |
| 3366 __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3359 __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 3367 } | 3360 } |
| 3368 | 3361 |
| 3369 | 3362 |
| 3370 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3363 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3371 int formal_parameter_count, | 3364 int formal_parameter_count, |
| 3372 int arity, | 3365 int arity, |
| 3373 LInstruction* instr, | 3366 LInstruction* instr, |
| 3374 CallKind call_kind, | |
| 3375 RDIState rdi_state) { | 3367 RDIState rdi_state) { |
| 3376 bool dont_adapt_arguments = | 3368 bool dont_adapt_arguments = |
| 3377 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3369 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3378 bool can_invoke_directly = | 3370 bool can_invoke_directly = |
| 3379 dont_adapt_arguments || formal_parameter_count == arity; | 3371 dont_adapt_arguments || formal_parameter_count == arity; |
| 3380 | 3372 |
| 3381 LPointerMap* pointers = instr->pointer_map(); | 3373 LPointerMap* pointers = instr->pointer_map(); |
| 3382 | 3374 |
| 3383 if (can_invoke_directly) { | 3375 if (can_invoke_directly) { |
| 3384 if (rdi_state == RDI_UNINITIALIZED) { | 3376 if (rdi_state == RDI_UNINITIALIZED) { |
| 3385 __ Move(rdi, function); | 3377 __ Move(rdi, function); |
| 3386 } | 3378 } |
| 3387 | 3379 |
| 3388 // Change context. | 3380 // Change context. |
| 3389 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 3381 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 3390 | 3382 |
| 3391 // Set rax to arguments count if adaption is not needed. Assumes that rax | 3383 // Set rax to arguments count if adaption is not needed. Assumes that rax |
| 3392 // is available to write to at this point. | 3384 // is available to write to at this point. |
| 3393 if (dont_adapt_arguments) { | 3385 if (dont_adapt_arguments) { |
| 3394 __ Set(rax, arity); | 3386 __ Set(rax, arity); |
| 3395 } | 3387 } |
| 3396 | 3388 |
| 3397 // Invoke function. | 3389 // Invoke function. |
| 3398 __ SetCallKind(rcx, call_kind); | |
| 3399 if (function.is_identical_to(info()->closure())) { | 3390 if (function.is_identical_to(info()->closure())) { |
| 3400 __ CallSelf(); | 3391 __ CallSelf(); |
| 3401 } else { | 3392 } else { |
| 3402 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 3393 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 3403 } | 3394 } |
| 3404 | 3395 |
| 3405 // Set up deoptimization. | 3396 // Set up deoptimization. |
| 3406 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 3397 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 3407 } else { | 3398 } else { |
| 3408 // We need to adapt arguments. | 3399 // We need to adapt arguments. |
| 3409 SafepointGenerator generator( | 3400 SafepointGenerator generator( |
| 3410 this, pointers, Safepoint::kLazyDeopt); | 3401 this, pointers, Safepoint::kLazyDeopt); |
| 3411 ParameterCount count(arity); | 3402 ParameterCount count(arity); |
| 3412 ParameterCount expected(formal_parameter_count); | 3403 ParameterCount expected(formal_parameter_count); |
| 3413 __ InvokeFunction( | 3404 __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator); |
| 3414 function, expected, count, CALL_FUNCTION, generator, call_kind); | |
| 3415 } | 3405 } |
| 3416 } | 3406 } |
| 3417 | 3407 |
| 3418 | 3408 |
| 3419 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3409 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
| 3420 ASSERT(ToRegister(instr->result()).is(rax)); | 3410 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3421 CallKnownFunction(instr->hydrogen()->function(), | 3411 |
| 3422 instr->hydrogen()->formal_parameter_count(), | 3412 LPointerMap* pointers = instr->pointer_map(); |
| 3423 instr->arity(), | 3413 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3424 instr, | 3414 |
| 3425 CALL_AS_FUNCTION, | 3415 if (instr->target()->IsConstantOperand()) { |
| 3426 RDI_UNINITIALIZED); | 3416 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
| 3417 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
| 3418 generator.BeforeCall(__ CallSize(code)); |
| 3419 __ call(code, RelocInfo::CODE_TARGET); |
| 3420 } else { |
| 3421 ASSERT(instr->target()->IsRegister()); |
| 3422 Register target = ToRegister(instr->target()); |
| 3423 generator.BeforeCall(__ CallSize(target)); |
| 3424 __ addq(target, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 3425 __ call(target); |
| 3426 } |
| 3427 generator.AfterCall(); |
| 3427 } | 3428 } |
| 3428 | 3429 |
| 3429 | 3430 |
| 3431 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
| 3432 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3433 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3434 |
| 3435 if (instr->hydrogen()->pass_argument_count()) { |
| 3436 __ Set(rax, instr->arity()); |
| 3437 } |
| 3438 |
| 3439 // Change context. |
| 3440 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 3441 |
| 3442 LPointerMap* pointers = instr->pointer_map(); |
| 3443 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3444 |
| 3445 bool is_self_call = false; |
| 3446 if (instr->hydrogen()->function()->IsConstant()) { |
| 3447 Handle<JSFunction> jsfun = Handle<JSFunction>::null(); |
| 3448 HConstant* fun_const = HConstant::cast(instr->hydrogen()->function()); |
| 3449 jsfun = Handle<JSFunction>::cast(fun_const->handle(isolate())); |
| 3450 is_self_call = jsfun.is_identical_to(info()->closure()); |
| 3451 } |
| 3452 |
| 3453 if (is_self_call) { |
| 3454 __ CallSelf(); |
| 3455 } else { |
| 3456 Operand target = FieldOperand(rdi, JSFunction::kCodeEntryOffset); |
| 3457 generator.BeforeCall(__ CallSize(target)); |
| 3458 __ call(target); |
| 3459 } |
| 3460 generator.AfterCall(); |
| 3461 } |
| 3462 |
| 3463 |
| 3430 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3464 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3431 Register input_reg = ToRegister(instr->value()); | 3465 Register input_reg = ToRegister(instr->value()); |
| 3432 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3466 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3433 Heap::kHeapNumberMapRootIndex); | 3467 Heap::kHeapNumberMapRootIndex); |
| 3434 DeoptimizeIf(not_equal, instr->environment()); | 3468 DeoptimizeIf(not_equal, instr->environment()); |
| 3435 | 3469 |
| 3436 Label slow, allocated, done; | 3470 Label slow, allocated, done; |
| 3437 Register tmp = input_reg.is(rax) ? rcx : rax; | 3471 Register tmp = input_reg.is(rax) ? rcx : rax; |
| 3438 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; | 3472 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; |
| 3439 | 3473 |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3774 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3808 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3775 ASSERT(ToRegister(instr->context()).is(rsi)); | 3809 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3776 ASSERT(ToRegister(instr->function()).is(rdi)); | 3810 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3777 ASSERT(instr->HasPointerMap()); | 3811 ASSERT(instr->HasPointerMap()); |
| 3778 | 3812 |
| 3779 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3813 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3780 if (known_function.is_null()) { | 3814 if (known_function.is_null()) { |
| 3781 LPointerMap* pointers = instr->pointer_map(); | 3815 LPointerMap* pointers = instr->pointer_map(); |
| 3782 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3816 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3783 ParameterCount count(instr->arity()); | 3817 ParameterCount count(instr->arity()); |
| 3784 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); | 3818 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator); |
| 3785 } else { | 3819 } else { |
| 3786 CallKnownFunction(known_function, | 3820 CallKnownFunction(known_function, |
| 3787 instr->hydrogen()->formal_parameter_count(), | 3821 instr->hydrogen()->formal_parameter_count(), |
| 3788 instr->arity(), | 3822 instr->arity(), |
| 3789 instr, | 3823 instr, |
| 3790 CALL_AS_FUNCTION, | |
| 3791 RDI_CONTAINS_TARGET); | 3824 RDI_CONTAINS_TARGET); |
| 3792 } | 3825 } |
| 3793 } | 3826 } |
| 3794 | 3827 |
| 3795 | 3828 |
| 3796 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | |
| 3797 ASSERT(ToRegister(instr->context()).is(rsi)); | |
| 3798 ASSERT(ToRegister(instr->key()).is(rcx)); | |
| 3799 ASSERT(ToRegister(instr->result()).is(rax)); | |
| 3800 | |
| 3801 int arity = instr->arity(); | |
| 3802 Handle<Code> ic = | |
| 3803 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | |
| 3804 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 3805 } | |
| 3806 | |
| 3807 | |
| 3808 void LCodeGen::DoCallNamed(LCallNamed* instr) { | |
| 3809 ASSERT(ToRegister(instr->context()).is(rsi)); | |
| 3810 ASSERT(ToRegister(instr->result()).is(rax)); | |
| 3811 | |
| 3812 int arity = instr->arity(); | |
| 3813 Handle<Code> ic = | |
| 3814 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); | |
| 3815 __ Move(rcx, instr->name()); | |
| 3816 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 3817 } | |
| 3818 | |
| 3819 | |
| 3820 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3829 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 3821 ASSERT(ToRegister(instr->context()).is(rsi)); | 3830 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3822 ASSERT(ToRegister(instr->function()).is(rdi)); | 3831 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3823 ASSERT(ToRegister(instr->result()).is(rax)); | 3832 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3824 | 3833 |
| 3825 int arity = instr->arity(); | 3834 int arity = instr->arity(); |
| 3826 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 3835 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 3827 if (instr->hydrogen()->IsTailCall()) { | 3836 if (instr->hydrogen()->IsTailCall()) { |
| 3828 if (NeedsEagerFrame()) __ leave(); | 3837 if (NeedsEagerFrame()) __ leave(); |
| 3829 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 3838 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
| 3830 } else { | 3839 } else { |
| 3831 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3840 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3832 } | 3841 } |
| 3833 } | 3842 } |
| 3834 | 3843 |
| 3835 | 3844 |
| 3836 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | |
| 3837 ASSERT(ToRegister(instr->context()).is(rsi)); | |
| 3838 ASSERT(ToRegister(instr->result()).is(rax)); | |
| 3839 int arity = instr->arity(); | |
| 3840 Handle<Code> ic = | |
| 3841 isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); | |
| 3842 __ Move(rcx, instr->name()); | |
| 3843 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 3844 } | |
| 3845 | |
| 3846 | |
| 3847 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | |
| 3848 ASSERT(ToRegister(instr->result()).is(rax)); | |
| 3849 CallKnownFunction(instr->hydrogen()->target(), | |
| 3850 instr->hydrogen()->formal_parameter_count(), | |
| 3851 instr->arity(), | |
| 3852 instr, | |
| 3853 CALL_AS_FUNCTION, | |
| 3854 RDI_UNINITIALIZED); | |
| 3855 } | |
| 3856 | |
| 3857 | |
| 3858 void LCodeGen::DoCallNew(LCallNew* instr) { | 3845 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3859 ASSERT(ToRegister(instr->context()).is(rsi)); | 3846 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3860 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3847 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3861 ASSERT(ToRegister(instr->result()).is(rax)); | 3848 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3862 | 3849 |
| 3863 __ Set(rax, instr->arity()); | 3850 __ Set(rax, instr->arity()); |
| 3864 // No cell in ebx for construct type feedback in optimized code | 3851 // No cell in ebx for construct type feedback in optimized code |
| 3865 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 3852 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 3866 __ Move(rbx, undefined_value); | 3853 __ Move(rbx, undefined_value); |
| 3867 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3854 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| (...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4988 __ Cmp(reg, instr->hydrogen()->object().handle()); | 4975 __ Cmp(reg, instr->hydrogen()->object().handle()); |
| 4989 DeoptimizeIf(not_equal, instr->environment()); | 4976 DeoptimizeIf(not_equal, instr->environment()); |
| 4990 } | 4977 } |
| 4991 | 4978 |
| 4992 | 4979 |
| 4993 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 4980 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 4994 { | 4981 { |
| 4995 PushSafepointRegistersScope scope(this); | 4982 PushSafepointRegistersScope scope(this); |
| 4996 __ push(object); | 4983 __ push(object); |
| 4997 __ Set(rsi, 0); | 4984 __ Set(rsi, 0); |
| 4998 __ CallRuntimeSaveDoubles(Runtime::kMigrateInstance); | 4985 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
| 4999 RecordSafepointWithRegisters( | 4986 RecordSafepointWithRegisters( |
| 5000 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 4987 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| 5001 | 4988 |
| 5002 __ testq(rax, Immediate(kSmiTagMask)); | 4989 __ testq(rax, Immediate(kSmiTagMask)); |
| 5003 } | 4990 } |
| 5004 DeoptimizeIf(zero, instr->environment()); | 4991 DeoptimizeIf(zero, instr->environment()); |
| 5005 } | 4992 } |
| 5006 | 4993 |
| 5007 | 4994 |
| 5008 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4995 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5417 __ movq(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); | 5404 __ movq(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); |
| 5418 | 5405 |
| 5419 // Check the marker in the calling frame. | 5406 // Check the marker in the calling frame. |
| 5420 __ bind(&check_frame_marker); | 5407 __ bind(&check_frame_marker); |
| 5421 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), | 5408 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
| 5422 Smi::FromInt(StackFrame::CONSTRUCT)); | 5409 Smi::FromInt(StackFrame::CONSTRUCT)); |
| 5423 } | 5410 } |
| 5424 | 5411 |
| 5425 | 5412 |
| 5426 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { | 5413 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
| 5427 if (info()->IsStub()) return; | 5414 if (!info()->IsStub()) { |
| 5428 // Ensure that we have enough space after the previous lazy-bailout | 5415 // Ensure that we have enough space after the previous lazy-bailout |
| 5429 // instruction for patching the code here. | 5416 // instruction for patching the code here. |
| 5430 int current_pc = masm()->pc_offset(); | 5417 int current_pc = masm()->pc_offset(); |
| 5431 if (current_pc < last_lazy_deopt_pc_ + space_needed) { | 5418 if (current_pc < last_lazy_deopt_pc_ + space_needed) { |
| 5432 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 5419 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 5433 __ Nop(padding_size); | 5420 __ Nop(padding_size); |
| 5421 } |
| 5434 } | 5422 } |
| 5423 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 5435 } | 5424 } |
| 5436 | 5425 |
| 5437 | 5426 |
| 5438 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 5427 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| 5439 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5428 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5440 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 5441 ASSERT(instr->HasEnvironment()); | 5429 ASSERT(instr->HasEnvironment()); |
| 5442 LEnvironment* env = instr->environment(); | 5430 LEnvironment* env = instr->environment(); |
| 5443 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5431 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5444 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5432 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5445 } | 5433 } |
| 5446 | 5434 |
| 5447 | 5435 |
| 5448 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5436 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 5449 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5437 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5450 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5438 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5503 Label done; | 5491 Label done; |
| 5504 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 5492 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 5505 __ j(above_equal, &done, Label::kNear); | 5493 __ j(above_equal, &done, Label::kNear); |
| 5506 | 5494 |
| 5507 ASSERT(instr->context()->IsRegister()); | 5495 ASSERT(instr->context()->IsRegister()); |
| 5508 ASSERT(ToRegister(instr->context()).is(rsi)); | 5496 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 5509 CallCode(isolate()->builtins()->StackCheck(), | 5497 CallCode(isolate()->builtins()->StackCheck(), |
| 5510 RelocInfo::CODE_TARGET, | 5498 RelocInfo::CODE_TARGET, |
| 5511 instr); | 5499 instr); |
| 5512 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5500 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5513 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 5514 __ bind(&done); | 5501 __ bind(&done); |
| 5515 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5502 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5516 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5503 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5517 } else { | 5504 } else { |
| 5518 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5505 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| 5519 // Perform stack overflow check if this goto needs it before jumping. | 5506 // Perform stack overflow check if this goto needs it before jumping. |
| 5520 DeferredStackCheck* deferred_stack_check = | 5507 DeferredStackCheck* deferred_stack_check = |
| 5521 new(zone()) DeferredStackCheck(this, instr); | 5508 new(zone()) DeferredStackCheck(this, instr); |
| 5522 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 5509 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 5523 __ j(below, deferred_stack_check->entry()); | 5510 __ j(below, deferred_stack_check->entry()); |
| 5524 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5511 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5525 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 5526 __ bind(instr->done_label()); | 5512 __ bind(instr->done_label()); |
| 5527 deferred_stack_check->SetExit(instr->done_label()); | 5513 deferred_stack_check->SetExit(instr->done_label()); |
| 5528 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5514 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5529 // Don't record a deoptimization index for the safepoint here. | 5515 // Don't record a deoptimization index for the safepoint here. |
| 5530 // This will be done explicitly when emitting call and the safepoint in | 5516 // This will be done explicitly when emitting call and the safepoint in |
| 5531 // the deferred code. | 5517 // the deferred code. |
| 5532 } | 5518 } |
| 5533 } | 5519 } |
| 5534 | 5520 |
| 5535 | 5521 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5636 FixedArray::kHeaderSize - kPointerSize)); | 5622 FixedArray::kHeaderSize - kPointerSize)); |
| 5637 __ bind(&done); | 5623 __ bind(&done); |
| 5638 } | 5624 } |
| 5639 | 5625 |
| 5640 | 5626 |
| 5641 #undef __ | 5627 #undef __ |
| 5642 | 5628 |
| 5643 } } // namespace v8::internal | 5629 } } // namespace v8::internal |
| 5644 | 5630 |
| 5645 #endif // V8_TARGET_ARCH_X64 | 5631 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |