| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved.7 |
| 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 139 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 140 __ stop("stop_at"); | 140 __ stop("stop_at"); |
| 141 } | 141 } |
| 142 #endif | 142 #endif |
| 143 | 143 |
| 144 // a1: Callee's JS function. | 144 // a1: Callee's JS function. |
| 145 // cp: Callee's context. | 145 // cp: Callee's context. |
| 146 // fp: Caller's frame pointer. | 146 // fp: Caller's frame pointer. |
| 147 // lr: Caller's pc. | 147 // lr: Caller's pc. |
| 148 | 148 |
| 149 // Strict mode functions and builtins need to replace the receiver | 149 // Classic mode functions and builtins need to replace the receiver with the |
| 150 // with undefined when called as functions (without an explicit | 150 // global proxy when called as functions (without an explicit receiver |
| 151 // receiver object). r5 is zero for method calls and non-zero for | 151 // object). |
| 152 // function calls. | 152 if (info_->this_has_uses() && |
| 153 if (!info_->is_classic_mode() || info_->is_native()) { | 153 info_->is_classic_mode() && |
| 154 !info_->is_native()) { |
| 154 Label ok; | 155 Label ok; |
| 155 __ Branch(&ok, eq, t1, Operand(zero_reg)); | 156 int receiver_offset = info_->scope()->num_parameters() * kPointerSize; |
| 157 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 158 __ lw(a2, MemOperand(sp, receiver_offset)); |
| 159 __ Branch(&ok, ne, a2, Operand(at)); |
| 156 | 160 |
| 157 int receiver_offset = scope()->num_parameters() * kPointerSize; | 161 __ lw(a2, GlobalObjectOperand()); |
| 158 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | 162 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); |
| 163 |
| 159 __ sw(a2, MemOperand(sp, receiver_offset)); | 164 __ sw(a2, MemOperand(sp, receiver_offset)); |
| 165 |
| 160 __ bind(&ok); | 166 __ bind(&ok); |
| 161 } | 167 } |
| 162 } | 168 } |
| 163 | 169 |
| 164 info()->set_prologue_offset(masm_->pc_offset()); | 170 info()->set_prologue_offset(masm_->pc_offset()); |
| 165 if (NeedsEagerFrame()) { | 171 if (NeedsEagerFrame()) { |
| 166 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); | 172 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
| 167 frame_is_built_ = true; | 173 frame_is_built_ = true; |
| 168 info_->AddNoFrameRange(0, masm_->pc_offset()); | 174 info_->AddNoFrameRange(0, masm_->pc_offset()); |
| 169 } | 175 } |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 RelocInfo::Mode mode, | 685 RelocInfo::Mode mode, |
| 680 LInstruction* instr) { | 686 LInstruction* instr) { |
| 681 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); | 687 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 682 } | 688 } |
| 683 | 689 |
| 684 | 690 |
| 685 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 691 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 686 RelocInfo::Mode mode, | 692 RelocInfo::Mode mode, |
| 687 LInstruction* instr, | 693 LInstruction* instr, |
| 688 SafepointMode safepoint_mode) { | 694 SafepointMode safepoint_mode) { |
| 689 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | |
| 690 ASSERT(instr != NULL); | 695 ASSERT(instr != NULL); |
| 691 __ Call(code, mode); | 696 __ Call(code, mode); |
| 692 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 697 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 693 } | 698 } |
| 694 | 699 |
| 695 | 700 |
| 696 void LCodeGen::CallRuntime(const Runtime::Function* function, | 701 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 697 int num_arguments, | 702 int num_arguments, |
| 698 LInstruction* instr, | 703 LInstruction* instr, |
| 699 SaveFPRegsMode save_doubles) { | 704 SaveFPRegsMode save_doubles) { |
| (...skipping 2663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3363 // Deoptimize if the receiver is not a JS object. | 3368 // Deoptimize if the receiver is not a JS object. |
| 3364 __ SmiTst(receiver, scratch); | 3369 __ SmiTst(receiver, scratch); |
| 3365 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); | 3370 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); |
| 3366 | 3371 |
| 3367 __ GetObjectType(receiver, scratch, scratch); | 3372 __ GetObjectType(receiver, scratch, scratch); |
| 3368 DeoptimizeIf(lt, instr->environment(), | 3373 DeoptimizeIf(lt, instr->environment(), |
| 3369 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); | 3374 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 3370 __ Branch(&result_in_receiver); | 3375 __ Branch(&result_in_receiver); |
| 3371 | 3376 |
| 3372 __ bind(&global_object); | 3377 __ bind(&global_object); |
| 3373 CallStubCompiler::FetchGlobalProxy(masm(), receiver, function); | 3378 __ lw(receiver, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3379 __ lw(receiver, |
| 3380 ContextOperand(receiver, Context::GLOBAL_OBJECT_INDEX)); |
| 3381 __ lw(receiver, |
| 3382 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
| 3374 | 3383 |
| 3375 if (result.is(receiver)) { | 3384 if (result.is(receiver)) { |
| 3376 __ bind(&result_in_receiver); | 3385 __ bind(&result_in_receiver); |
| 3377 } else { | 3386 } else { |
| 3378 Label result_ok; | 3387 Label result_ok; |
| 3379 __ Branch(&result_ok); | 3388 __ Branch(&result_ok); |
| 3380 __ bind(&result_in_receiver); | 3389 __ bind(&result_in_receiver); |
| 3381 __ mov(result, receiver); | 3390 __ mov(result, receiver); |
| 3382 __ bind(&result_ok); | 3391 __ bind(&result_ok); |
| 3383 } | 3392 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3421 __ sll(scratch, length, 2); | 3430 __ sll(scratch, length, 2); |
| 3422 | 3431 |
| 3423 __ bind(&invoke); | 3432 __ bind(&invoke); |
| 3424 ASSERT(instr->HasPointerMap()); | 3433 ASSERT(instr->HasPointerMap()); |
| 3425 LPointerMap* pointers = instr->pointer_map(); | 3434 LPointerMap* pointers = instr->pointer_map(); |
| 3426 SafepointGenerator safepoint_generator( | 3435 SafepointGenerator safepoint_generator( |
| 3427 this, pointers, Safepoint::kLazyDeopt); | 3436 this, pointers, Safepoint::kLazyDeopt); |
| 3428 // The number of arguments is stored in receiver which is a0, as expected | 3437 // The number of arguments is stored in receiver which is a0, as expected |
| 3429 // by InvokeFunction. | 3438 // by InvokeFunction. |
| 3430 ParameterCount actual(receiver); | 3439 ParameterCount actual(receiver); |
| 3431 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3440 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); |
| 3432 safepoint_generator, CALL_AS_METHOD); | |
| 3433 } | 3441 } |
| 3434 | 3442 |
| 3435 | 3443 |
| 3436 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3444 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3437 LOperand* argument = instr->value(); | 3445 LOperand* argument = instr->value(); |
| 3438 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3446 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 3439 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3447 Abort(kDoPushArgumentNotImplementedForDoubleType); |
| 3440 } else { | 3448 } else { |
| 3441 Register argument_reg = EmitLoadRegister(argument, at); | 3449 Register argument_reg = EmitLoadRegister(argument, at); |
| 3442 __ push(argument_reg); | 3450 __ push(argument_reg); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3496 Register global = ToRegister(instr->global_object()); | 3504 Register global = ToRegister(instr->global_object()); |
| 3497 Register result = ToRegister(instr->result()); | 3505 Register result = ToRegister(instr->result()); |
| 3498 __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3506 __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 3499 } | 3507 } |
| 3500 | 3508 |
| 3501 | 3509 |
| 3502 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3510 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3503 int formal_parameter_count, | 3511 int formal_parameter_count, |
| 3504 int arity, | 3512 int arity, |
| 3505 LInstruction* instr, | 3513 LInstruction* instr, |
| 3506 CallKind call_kind, | |
| 3507 A1State a1_state) { | 3514 A1State a1_state) { |
| 3508 bool dont_adapt_arguments = | 3515 bool dont_adapt_arguments = |
| 3509 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3516 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3510 bool can_invoke_directly = | 3517 bool can_invoke_directly = |
| 3511 dont_adapt_arguments || formal_parameter_count == arity; | 3518 dont_adapt_arguments || formal_parameter_count == arity; |
| 3512 | 3519 |
| 3513 LPointerMap* pointers = instr->pointer_map(); | 3520 LPointerMap* pointers = instr->pointer_map(); |
| 3514 | 3521 |
| 3515 if (can_invoke_directly) { | 3522 if (can_invoke_directly) { |
| 3516 if (a1_state == A1_UNINITIALIZED) { | 3523 if (a1_state == A1_UNINITIALIZED) { |
| 3517 __ li(a1, function); | 3524 __ li(a1, function); |
| 3518 } | 3525 } |
| 3519 | 3526 |
| 3520 // Change context. | 3527 // Change context. |
| 3521 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 3528 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 3522 | 3529 |
| 3523 // Set r0 to arguments count if adaption is not needed. Assumes that r0 | 3530 // Set r0 to arguments count if adaption is not needed. Assumes that r0 |
| 3524 // is available to write to at this point. | 3531 // is available to write to at this point. |
| 3525 if (dont_adapt_arguments) { | 3532 if (dont_adapt_arguments) { |
| 3526 __ li(a0, Operand(arity)); | 3533 __ li(a0, Operand(arity)); |
| 3527 } | 3534 } |
| 3528 | 3535 |
| 3529 // Invoke function. | 3536 // Invoke function. |
| 3530 __ SetCallKind(t1, call_kind); | |
| 3531 __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 3537 __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 3532 __ Call(at); | 3538 __ Call(at); |
| 3533 | 3539 |
| 3534 // Set up deoptimization. | 3540 // Set up deoptimization. |
| 3535 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3541 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3536 } else { | 3542 } else { |
| 3537 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3543 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3538 ParameterCount count(arity); | 3544 ParameterCount count(arity); |
| 3539 ParameterCount expected(formal_parameter_count); | 3545 ParameterCount expected(formal_parameter_count); |
| 3540 __ InvokeFunction( | 3546 __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator); |
| 3541 function, expected, count, CALL_FUNCTION, generator, call_kind); | |
| 3542 } | 3547 } |
| 3543 } | 3548 } |
| 3544 | 3549 |
| 3545 | 3550 |
| 3546 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | |
| 3547 ASSERT(ToRegister(instr->result()).is(v0)); | |
| 3548 __ mov(a0, v0); | |
| 3549 CallKnownFunction(instr->hydrogen()->function(), | |
| 3550 instr->hydrogen()->formal_parameter_count(), | |
| 3551 instr->arity(), | |
| 3552 instr, | |
| 3553 CALL_AS_METHOD, | |
| 3554 A1_UNINITIALIZED); | |
| 3555 } | |
| 3556 | |
| 3557 | |
| 3558 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3551 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3559 ASSERT(instr->context() != NULL); | 3552 ASSERT(instr->context() != NULL); |
| 3560 ASSERT(ToRegister(instr->context()).is(cp)); | 3553 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3561 Register input = ToRegister(instr->value()); | 3554 Register input = ToRegister(instr->value()); |
| 3562 Register result = ToRegister(instr->result()); | 3555 Register result = ToRegister(instr->result()); |
| 3563 Register scratch = scratch0(); | 3556 Register scratch = scratch0(); |
| 3564 | 3557 |
| 3565 // Deoptimize if not a heap number. | 3558 // Deoptimize if not a heap number. |
| 3566 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3559 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3567 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3560 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3866 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3859 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3867 ASSERT(ToRegister(instr->context()).is(cp)); | 3860 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3868 ASSERT(ToRegister(instr->function()).is(a1)); | 3861 ASSERT(ToRegister(instr->function()).is(a1)); |
| 3869 ASSERT(instr->HasPointerMap()); | 3862 ASSERT(instr->HasPointerMap()); |
| 3870 | 3863 |
| 3871 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3864 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3872 if (known_function.is_null()) { | 3865 if (known_function.is_null()) { |
| 3873 LPointerMap* pointers = instr->pointer_map(); | 3866 LPointerMap* pointers = instr->pointer_map(); |
| 3874 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3867 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3875 ParameterCount count(instr->arity()); | 3868 ParameterCount count(instr->arity()); |
| 3876 __ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3869 __ InvokeFunction(a1, count, CALL_FUNCTION, generator); |
| 3877 } else { | 3870 } else { |
| 3878 CallKnownFunction(known_function, | 3871 CallKnownFunction(known_function, |
| 3879 instr->hydrogen()->formal_parameter_count(), | 3872 instr->hydrogen()->formal_parameter_count(), |
| 3880 instr->arity(), | 3873 instr->arity(), |
| 3881 instr, | 3874 instr, |
| 3882 CALL_AS_METHOD, | |
| 3883 A1_CONTAINS_TARGET); | 3875 A1_CONTAINS_TARGET); |
| 3884 } | 3876 } |
| 3885 } | 3877 } |
| 3886 | 3878 |
| 3887 | 3879 |
| 3888 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 3880 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
| 3889 ASSERT(ToRegister(instr->context()).is(cp)); | |
| 3890 ASSERT(ToRegister(instr->result()).is(v0)); | 3881 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3891 | 3882 |
| 3892 int arity = instr->arity(); | 3883 LPointerMap* pointers = instr->pointer_map(); |
| 3893 Handle<Code> ic = | 3884 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3894 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 3885 |
| 3895 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3886 if (instr->target()->IsConstantOperand()) { |
| 3887 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
| 3888 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
| 3889 generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); |
| 3890 __ Call(code, RelocInfo::CODE_TARGET); |
| 3891 } else { |
| 3892 ASSERT(instr->target()->IsRegister()); |
| 3893 Register target = ToRegister(instr->target()); |
| 3894 generator.BeforeCall(__ CallSize(target)); |
| 3895 __ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 3896 __ Call(target); |
| 3897 } |
| 3898 generator.AfterCall(); |
| 3896 } | 3899 } |
| 3897 | 3900 |
| 3898 | 3901 |
| 3899 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 3902 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
| 3900 ASSERT(ToRegister(instr->context()).is(cp)); | 3903 ASSERT(ToRegister(instr->function()).is(a1)); |
| 3901 ASSERT(ToRegister(instr->result()).is(v0)); | 3904 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3902 | 3905 |
| 3903 int arity = instr->arity(); | 3906 if (instr->hydrogen()->pass_argument_count()) { |
| 3904 Handle<Code> ic = | 3907 __ li(a0, Operand(instr->arity())); |
| 3905 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); | 3908 } |
| 3906 __ li(a2, Operand(instr->name())); | 3909 |
| 3907 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3910 // Change context. |
| 3911 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 3912 |
| 3913 // Load the code entry address |
| 3914 __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 3915 __ Call(at); |
| 3916 |
| 3917 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3908 } | 3918 } |
| 3909 | 3919 |
| 3910 | 3920 |
| 3911 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3921 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 3912 ASSERT(ToRegister(instr->context()).is(cp)); | 3922 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3913 ASSERT(ToRegister(instr->function()).is(a1)); | 3923 ASSERT(ToRegister(instr->function()).is(a1)); |
| 3914 ASSERT(ToRegister(instr->result()).is(v0)); | 3924 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3915 | 3925 |
| 3916 int arity = instr->arity(); | 3926 int arity = instr->arity(); |
| 3917 CallFunctionFlags flags = | 3927 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 3918 instr->hydrogen()->IsContextualCall() ? | |
| 3919 RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS; | |
| 3920 CallFunctionStub stub(arity, flags); | |
| 3921 if (instr->hydrogen()->IsTailCall()) { | 3928 if (instr->hydrogen()->IsTailCall()) { |
| 3922 if (NeedsEagerFrame()) __ mov(sp, fp); | 3929 if (NeedsEagerFrame()) __ mov(sp, fp); |
| 3923 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 3930 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
| 3924 } else { | 3931 } else { |
| 3925 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3932 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3926 } | 3933 } |
| 3927 } | 3934 } |
| 3928 | 3935 |
| 3929 | 3936 |
| 3930 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | |
| 3931 ASSERT(ToRegister(instr->context()).is(cp)); | |
| 3932 ASSERT(ToRegister(instr->result()).is(v0)); | |
| 3933 | |
| 3934 int arity = instr->arity(); | |
| 3935 Handle<Code> ic = | |
| 3936 isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); | |
| 3937 __ li(a2, Operand(instr->name())); | |
| 3938 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 3939 } | |
| 3940 | |
| 3941 | |
| 3942 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | |
| 3943 ASSERT(ToRegister(instr->result()).is(v0)); | |
| 3944 CallKnownFunction(instr->hydrogen()->target(), | |
| 3945 instr->hydrogen()->formal_parameter_count(), | |
| 3946 instr->arity(), | |
| 3947 instr, | |
| 3948 CALL_AS_FUNCTION, | |
| 3949 A1_UNINITIALIZED); | |
| 3950 } | |
| 3951 | |
| 3952 | |
| 3953 void LCodeGen::DoCallNew(LCallNew* instr) { | 3937 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3954 ASSERT(ToRegister(instr->context()).is(cp)); | 3938 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3955 ASSERT(ToRegister(instr->constructor()).is(a1)); | 3939 ASSERT(ToRegister(instr->constructor()).is(a1)); |
| 3956 ASSERT(ToRegister(instr->result()).is(v0)); | 3940 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3957 | 3941 |
| 3958 __ li(a0, Operand(instr->arity())); | 3942 __ li(a0, Operand(instr->arity())); |
| 3959 // No cell in a2 for construct type feedback in optimized code | 3943 // No cell in a2 for construct type feedback in optimized code |
| 3960 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 3944 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 3961 __ li(a2, Operand(undefined_value)); | 3945 __ li(a2, Operand(undefined_value)); |
| 3962 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3946 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| (...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5120 Operand(object)); | 5104 Operand(object)); |
| 5121 } | 5105 } |
| 5122 } | 5106 } |
| 5123 | 5107 |
| 5124 | 5108 |
| 5125 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5109 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 5126 { | 5110 { |
| 5127 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5111 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5128 __ push(object); | 5112 __ push(object); |
| 5129 __ mov(cp, zero_reg); | 5113 __ mov(cp, zero_reg); |
| 5130 __ CallRuntimeSaveDoubles(Runtime::kMigrateInstance); | 5114 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
| 5131 RecordSafepointWithRegisters( | 5115 RecordSafepointWithRegisters( |
| 5132 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 5116 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| 5133 __ StoreToSafepointRegisterSlot(v0, scratch0()); | 5117 __ StoreToSafepointRegisterSlot(v0, scratch0()); |
| 5134 } | 5118 } |
| 5135 __ SmiTst(scratch0(), at); | 5119 __ SmiTst(scratch0(), at); |
| 5136 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5120 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); |
| 5137 } | 5121 } |
| 5138 | 5122 |
| 5139 | 5123 |
| 5140 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5124 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5583 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 5567 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 5584 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); | 5568 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); |
| 5585 | 5569 |
| 5586 // Check the marker in the calling frame. | 5570 // Check the marker in the calling frame. |
| 5587 __ bind(&check_frame_marker); | 5571 __ bind(&check_frame_marker); |
| 5588 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); | 5572 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); |
| 5589 } | 5573 } |
| 5590 | 5574 |
| 5591 | 5575 |
| 5592 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { | 5576 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
| 5593 if (info()->IsStub()) return; | 5577 if (!info()->IsStub()) { |
| 5594 // Ensure that we have enough space after the previous lazy-bailout | 5578 // Ensure that we have enough space after the previous lazy-bailout |
| 5595 // instruction for patching the code here. | 5579 // instruction for patching the code here. |
| 5596 int current_pc = masm()->pc_offset(); | 5580 int current_pc = masm()->pc_offset(); |
| 5597 if (current_pc < last_lazy_deopt_pc_ + space_needed) { | 5581 if (current_pc < last_lazy_deopt_pc_ + space_needed) { |
| 5598 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 5582 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 5599 ASSERT_EQ(0, padding_size % Assembler::kInstrSize); | 5583 ASSERT_EQ(0, padding_size % Assembler::kInstrSize); |
| 5600 while (padding_size > 0) { | 5584 while (padding_size > 0) { |
| 5601 __ nop(); | 5585 __ nop(); |
| 5602 padding_size -= Assembler::kInstrSize; | 5586 padding_size -= Assembler::kInstrSize; |
| 5587 } |
| 5603 } | 5588 } |
| 5604 } | 5589 } |
| 5590 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 5605 } | 5591 } |
| 5606 | 5592 |
| 5607 | 5593 |
| 5608 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 5594 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| 5609 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5595 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5610 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 5611 ASSERT(instr->HasEnvironment()); | 5596 ASSERT(instr->HasEnvironment()); |
| 5612 LEnvironment* env = instr->environment(); | 5597 LEnvironment* env = instr->environment(); |
| 5613 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5598 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5614 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5599 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5615 } | 5600 } |
| 5616 | 5601 |
| 5617 | 5602 |
| 5618 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5603 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 5619 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5604 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5620 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5605 // 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... |
| 5673 // Perform stack overflow check. | 5658 // Perform stack overflow check. |
| 5674 Label done; | 5659 Label done; |
| 5675 __ LoadRoot(at, Heap::kStackLimitRootIndex); | 5660 __ LoadRoot(at, Heap::kStackLimitRootIndex); |
| 5676 __ Branch(&done, hs, sp, Operand(at)); | 5661 __ Branch(&done, hs, sp, Operand(at)); |
| 5677 ASSERT(instr->context()->IsRegister()); | 5662 ASSERT(instr->context()->IsRegister()); |
| 5678 ASSERT(ToRegister(instr->context()).is(cp)); | 5663 ASSERT(ToRegister(instr->context()).is(cp)); |
| 5679 CallCode(isolate()->builtins()->StackCheck(), | 5664 CallCode(isolate()->builtins()->StackCheck(), |
| 5680 RelocInfo::CODE_TARGET, | 5665 RelocInfo::CODE_TARGET, |
| 5681 instr); | 5666 instr); |
| 5682 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5667 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5683 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 5684 __ bind(&done); | 5668 __ bind(&done); |
| 5685 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5669 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5686 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5670 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5687 } else { | 5671 } else { |
| 5688 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5672 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| 5689 // Perform stack overflow check if this goto needs it before jumping. | 5673 // Perform stack overflow check if this goto needs it before jumping. |
| 5690 DeferredStackCheck* deferred_stack_check = | 5674 DeferredStackCheck* deferred_stack_check = |
| 5691 new(zone()) DeferredStackCheck(this, instr); | 5675 new(zone()) DeferredStackCheck(this, instr); |
| 5692 __ LoadRoot(at, Heap::kStackLimitRootIndex); | 5676 __ LoadRoot(at, Heap::kStackLimitRootIndex); |
| 5693 __ Branch(deferred_stack_check->entry(), lo, sp, Operand(at)); | 5677 __ Branch(deferred_stack_check->entry(), lo, sp, Operand(at)); |
| 5694 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5678 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5695 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 5696 __ bind(instr->done_label()); | 5679 __ bind(instr->done_label()); |
| 5697 deferred_stack_check->SetExit(instr->done_label()); | 5680 deferred_stack_check->SetExit(instr->done_label()); |
| 5698 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5681 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5699 // Don't record a deoptimization index for the safepoint here. | 5682 // Don't record a deoptimization index for the safepoint here. |
| 5700 // This will be done explicitly when emitting call and the safepoint in | 5683 // This will be done explicitly when emitting call and the safepoint in |
| 5701 // the deferred code. | 5684 // the deferred code. |
| 5702 } | 5685 } |
| 5703 } | 5686 } |
| 5704 | 5687 |
| 5705 | 5688 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5806 __ Subu(scratch, result, scratch); | 5789 __ Subu(scratch, result, scratch); |
| 5807 __ lw(result, FieldMemOperand(scratch, | 5790 __ lw(result, FieldMemOperand(scratch, |
| 5808 FixedArray::kHeaderSize - kPointerSize)); | 5791 FixedArray::kHeaderSize - kPointerSize)); |
| 5809 __ bind(&done); | 5792 __ bind(&done); |
| 5810 } | 5793 } |
| 5811 | 5794 |
| 5812 | 5795 |
| 5813 #undef __ | 5796 #undef __ |
| 5814 | 5797 |
| 5815 } } // namespace v8::internal | 5798 } } // namespace v8::internal |
| OLD | NEW |