| 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 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 972 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 984 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
| 973 kind, arguments, deopt_mode); | 985 kind, arguments, deopt_mode); |
| 974 for (int i = 0; i < operands->length(); i++) { | 986 for (int i = 0; i < operands->length(); i++) { |
| 975 LOperand* pointer = operands->at(i); | 987 LOperand* pointer = operands->at(i); |
| 976 if (pointer->IsStackSlot()) { | 988 if (pointer->IsStackSlot()) { |
| 977 safepoint.DefinePointerSlot(pointer->index(), zone()); | 989 safepoint.DefinePointerSlot(pointer->index(), zone()); |
| 978 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 990 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
| 979 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); | 991 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); |
| 980 } | 992 } |
| 981 } | 993 } |
| 994 if (FLAG_enable_ool_constant_pool && (kind & Safepoint::kWithRegisters)) { |
| 995 // Register pp always contains a pointer to the constant pool. |
| 996 safepoint.DefinePointerRegister(pp, zone()); |
| 997 } |
| 982 } | 998 } |
| 983 | 999 |
| 984 | 1000 |
| 985 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 1001 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 986 Safepoint::DeoptMode deopt_mode) { | 1002 Safepoint::DeoptMode deopt_mode) { |
| 987 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); | 1003 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); |
| 988 } | 1004 } |
| 989 | 1005 |
| 990 | 1006 |
| 991 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { | 1007 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 // Do the test only if it hadn't be done above. | 1417 // Do the test only if it hadn't be done above. |
| 1402 __ cmp(right, Operand::Zero()); | 1418 __ cmp(right, Operand::Zero()); |
| 1403 } | 1419 } |
| 1404 __ b(pl, &positive); | 1420 __ b(pl, &positive); |
| 1405 __ cmp(left, Operand::Zero()); | 1421 __ cmp(left, Operand::Zero()); |
| 1406 DeoptimizeIf(eq, instr->environment()); | 1422 DeoptimizeIf(eq, instr->environment()); |
| 1407 __ bind(&positive); | 1423 __ bind(&positive); |
| 1408 } | 1424 } |
| 1409 | 1425 |
| 1410 // Check for (kMinInt / -1). | 1426 // Check for (kMinInt / -1). |
| 1411 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1427 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow) && |
| 1428 (!CpuFeatures::IsSupported(SUDIV) || |
| 1429 !instr->hydrogen()->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
| 1430 // We don't need to check for overflow when truncating with sdiv |
| 1431 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. |
| 1412 __ cmp(left, Operand(kMinInt)); | 1432 __ cmp(left, Operand(kMinInt)); |
| 1413 __ cmp(right, Operand(-1), eq); | 1433 __ cmp(right, Operand(-1), eq); |
| 1414 DeoptimizeIf(eq, instr->environment()); | 1434 DeoptimizeIf(eq, instr->environment()); |
| 1415 } | 1435 } |
| 1416 | 1436 |
| 1417 if (CpuFeatures::IsSupported(SUDIV)) { | 1437 if (CpuFeatures::IsSupported(SUDIV)) { |
| 1418 CpuFeatureScope scope(masm(), SUDIV); | 1438 CpuFeatureScope scope(masm(), SUDIV); |
| 1419 __ sdiv(result, left, right); | 1439 __ sdiv(result, left, right); |
| 1420 | 1440 |
| 1421 if (!instr->hydrogen()->CheckFlag( | 1441 if (!instr->hydrogen()->CheckFlag( |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2113 __ vsub(result, left, right); | 2133 __ vsub(result, left, right); |
| 2114 break; | 2134 break; |
| 2115 case Token::MUL: | 2135 case Token::MUL: |
| 2116 __ vmul(result, left, right); | 2136 __ vmul(result, left, right); |
| 2117 break; | 2137 break; |
| 2118 case Token::DIV: | 2138 case Token::DIV: |
| 2119 __ vdiv(result, left, right); | 2139 __ vdiv(result, left, right); |
| 2120 break; | 2140 break; |
| 2121 case Token::MOD: { | 2141 case Token::MOD: { |
| 2122 __ PrepareCallCFunction(0, 2, scratch0()); | 2142 __ PrepareCallCFunction(0, 2, scratch0()); |
| 2123 __ SetCallCDoubleArguments(left, right); | 2143 __ MovToFloatParameters(left, right); |
| 2124 __ CallCFunction( | 2144 __ CallCFunction( |
| 2125 ExternalReference::mod_two_doubles_operation(isolate()), | 2145 ExternalReference::mod_two_doubles_operation(isolate()), |
| 2126 0, 2); | 2146 0, 2); |
| 2127 // Move the result in the double result register. | 2147 // Move the result in the double result register. |
| 2128 __ GetCFunctionDoubleResult(result); | 2148 __ MovFromFloatResult(result); |
| 2129 break; | 2149 break; |
| 2130 } | 2150 } |
| 2131 default: | 2151 default: |
| 2132 UNREACHABLE(); | 2152 UNREACHABLE(); |
| 2133 break; | 2153 break; |
| 2134 } | 2154 } |
| 2135 } | 2155 } |
| 2136 | 2156 |
| 2137 | 2157 |
| 2138 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2158 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| (...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2947 } | 2967 } |
| 2948 } | 2968 } |
| 2949 | 2969 |
| 2950 | 2970 |
| 2951 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2971 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 2952 ASSERT(ToRegister(instr->context()).is(cp)); | 2972 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2953 ASSERT(ToRegister(instr->global_object()).is(r0)); | 2973 ASSERT(ToRegister(instr->global_object()).is(r0)); |
| 2954 ASSERT(ToRegister(instr->result()).is(r0)); | 2974 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2955 | 2975 |
| 2956 __ mov(r2, Operand(instr->name())); | 2976 __ mov(r2, Operand(instr->name())); |
| 2957 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET | 2977 ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; |
| 2958 : RelocInfo::CODE_TARGET_CONTEXT; | 2978 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); |
| 2959 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2979 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2960 CallCode(ic, mode, instr); | |
| 2961 } | 2980 } |
| 2962 | 2981 |
| 2963 | 2982 |
| 2964 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2983 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 2965 Register value = ToRegister(instr->value()); | 2984 Register value = ToRegister(instr->value()); |
| 2966 Register cell = scratch0(); | 2985 Register cell = scratch0(); |
| 2967 | 2986 |
| 2968 // Load the cell. | 2987 // Load the cell. |
| 2969 __ mov(cell, Operand(instr->hydrogen()->cell().handle())); | 2988 __ mov(cell, Operand(instr->hydrogen()->cell().handle())); |
| 2970 | 2989 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2985 // Cells are always rescanned, so no write barrier here. | 3004 // Cells are always rescanned, so no write barrier here. |
| 2986 } | 3005 } |
| 2987 | 3006 |
| 2988 | 3007 |
| 2989 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 3008 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
| 2990 ASSERT(ToRegister(instr->context()).is(cp)); | 3009 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2991 ASSERT(ToRegister(instr->global_object()).is(r1)); | 3010 ASSERT(ToRegister(instr->global_object()).is(r1)); |
| 2992 ASSERT(ToRegister(instr->value()).is(r0)); | 3011 ASSERT(ToRegister(instr->value()).is(r0)); |
| 2993 | 3012 |
| 2994 __ mov(r2, Operand(instr->name())); | 3013 __ mov(r2, Operand(instr->name())); |
| 2995 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3014 Handle<Code> ic = StoreIC::initialize_stub(isolate(), |
| 2996 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3015 instr->strict_mode_flag(), |
| 2997 : isolate()->builtins()->StoreIC_Initialize(); | 3016 CONTEXTUAL); |
| 2998 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 3017 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2999 } | 3018 } |
| 3000 | 3019 |
| 3001 | 3020 |
| 3002 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 3021 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 3003 Register context = ToRegister(instr->context()); | 3022 Register context = ToRegister(instr->context()); |
| 3004 Register result = ToRegister(instr->result()); | 3023 Register result = ToRegister(instr->result()); |
| 3005 __ ldr(result, ContextOperand(context, instr->slot_index())); | 3024 __ ldr(result, ContextOperand(context, instr->slot_index())); |
| 3006 if (instr->hydrogen()->RequiresHoleCheck()) { | 3025 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3007 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3026 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3008 __ cmp(result, ip); | 3027 __ cmp(result, ip); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3081 } | 3100 } |
| 3082 | 3101 |
| 3083 | 3102 |
| 3084 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3103 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 3085 ASSERT(ToRegister(instr->context()).is(cp)); | 3104 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3086 ASSERT(ToRegister(instr->object()).is(r0)); | 3105 ASSERT(ToRegister(instr->object()).is(r0)); |
| 3087 ASSERT(ToRegister(instr->result()).is(r0)); | 3106 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3088 | 3107 |
| 3089 // Name is always in r2. | 3108 // Name is always in r2. |
| 3090 __ mov(r2, Operand(instr->name())); | 3109 __ mov(r2, Operand(instr->name())); |
| 3091 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3110 Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); |
| 3092 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3111 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 3093 } | 3112 } |
| 3094 | 3113 |
| 3095 | 3114 |
| 3096 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 3115 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 3097 Register scratch = scratch0(); | 3116 Register scratch = scratch0(); |
| 3098 Register function = ToRegister(instr->function()); | 3117 Register function = ToRegister(instr->function()); |
| 3099 Register result = ToRegister(instr->result()); | 3118 Register result = ToRegister(instr->result()); |
| 3100 | 3119 |
| 3101 // Check that the function really is a function. Load map into the | 3120 // Check that the function really is a function. Load map into the |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3480 __ b(eq, &global_object); | 3499 __ b(eq, &global_object); |
| 3481 | 3500 |
| 3482 // Deoptimize if the receiver is not a JS object. | 3501 // Deoptimize if the receiver is not a JS object. |
| 3483 __ SmiTst(receiver); | 3502 __ SmiTst(receiver); |
| 3484 DeoptimizeIf(eq, instr->environment()); | 3503 DeoptimizeIf(eq, instr->environment()); |
| 3485 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); | 3504 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); |
| 3486 DeoptimizeIf(lt, instr->environment()); | 3505 DeoptimizeIf(lt, instr->environment()); |
| 3487 __ b(&result_in_receiver); | 3506 __ b(&result_in_receiver); |
| 3488 | 3507 |
| 3489 __ bind(&global_object); | 3508 __ bind(&global_object); |
| 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)); |
| 3490 | 3515 |
| 3491 __ ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3492 __ ldr(result, ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); | |
| 3493 __ ldr(result, | |
| 3494 FieldMemOperand(result, JSGlobalObject::kGlobalReceiverOffset)); | |
| 3495 if (result.is(receiver)) { | 3516 if (result.is(receiver)) { |
| 3496 __ bind(&result_in_receiver); | 3517 __ bind(&result_in_receiver); |
| 3497 } else { | 3518 } else { |
| 3498 Label result_ok; | 3519 Label result_ok; |
| 3499 __ b(&result_ok); | 3520 __ b(&result_ok); |
| 3500 __ bind(&result_in_receiver); | 3521 __ bind(&result_in_receiver); |
| 3501 __ mov(result, receiver); | 3522 __ mov(result, receiver); |
| 3502 __ bind(&result_ok); | 3523 __ bind(&result_ok); |
| 3503 } | 3524 } |
| 3504 } | 3525 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3541 | 3562 |
| 3542 __ bind(&invoke); | 3563 __ bind(&invoke); |
| 3543 ASSERT(instr->HasPointerMap()); | 3564 ASSERT(instr->HasPointerMap()); |
| 3544 LPointerMap* pointers = instr->pointer_map(); | 3565 LPointerMap* pointers = instr->pointer_map(); |
| 3545 SafepointGenerator safepoint_generator( | 3566 SafepointGenerator safepoint_generator( |
| 3546 this, pointers, Safepoint::kLazyDeopt); | 3567 this, pointers, Safepoint::kLazyDeopt); |
| 3547 // 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 |
| 3548 // by InvokeFunction. | 3569 // by InvokeFunction. |
| 3549 ParameterCount actual(receiver); | 3570 ParameterCount actual(receiver); |
| 3550 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3571 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3551 safepoint_generator, CALL_AS_METHOD); | 3572 safepoint_generator, CALL_AS_FUNCTION); |
| 3552 } | 3573 } |
| 3553 | 3574 |
| 3554 | 3575 |
| 3555 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3576 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3556 LOperand* argument = instr->value(); | 3577 LOperand* argument = instr->value(); |
| 3557 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3578 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 3558 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3579 Abort(kDoPushArgumentNotImplementedForDoubleType); |
| 3559 } else { | 3580 } else { |
| 3560 Register argument_reg = EmitLoadRegister(argument, ip); | 3581 Register argument_reg = EmitLoadRegister(argument, ip); |
| 3561 __ push(argument_reg); | 3582 __ push(argument_reg); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3662 } | 3683 } |
| 3663 } | 3684 } |
| 3664 | 3685 |
| 3665 | 3686 |
| 3666 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3687 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 3667 ASSERT(ToRegister(instr->result()).is(r0)); | 3688 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3668 CallKnownFunction(instr->hydrogen()->function(), | 3689 CallKnownFunction(instr->hydrogen()->function(), |
| 3669 instr->hydrogen()->formal_parameter_count(), | 3690 instr->hydrogen()->formal_parameter_count(), |
| 3670 instr->arity(), | 3691 instr->arity(), |
| 3671 instr, | 3692 instr, |
| 3672 CALL_AS_METHOD, | 3693 CALL_AS_FUNCTION, |
| 3673 R1_UNINITIALIZED); | 3694 R1_UNINITIALIZED); |
| 3674 } | 3695 } |
| 3675 | 3696 |
| 3676 | 3697 |
| 3677 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3698 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3678 ASSERT(instr->context() != NULL); | 3699 ASSERT(instr->context() != NULL); |
| 3679 ASSERT(ToRegister(instr->context()).is(cp)); | 3700 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3680 Register input = ToRegister(instr->value()); | 3701 Register input = ToRegister(instr->value()); |
| 3681 Register result = ToRegister(instr->result()); | 3702 Register result = ToRegister(instr->result()); |
| 3682 Register scratch = scratch0(); | 3703 Register scratch = scratch0(); |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3923 Register temp2 = ToRegister(instr->temp2()); | 3944 Register temp2 = ToRegister(instr->temp2()); |
| 3924 | 3945 |
| 3925 MathExpGenerator::EmitMathExp( | 3946 MathExpGenerator::EmitMathExp( |
| 3926 masm(), input, result, double_scratch1, double_scratch2, | 3947 masm(), input, result, double_scratch1, double_scratch2, |
| 3927 temp1, temp2, scratch0()); | 3948 temp1, temp2, scratch0()); |
| 3928 } | 3949 } |
| 3929 | 3950 |
| 3930 | 3951 |
| 3931 void LCodeGen::DoMathLog(LMathLog* instr) { | 3952 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 3932 __ PrepareCallCFunction(0, 1, scratch0()); | 3953 __ PrepareCallCFunction(0, 1, scratch0()); |
| 3933 __ SetCallCDoubleArguments(ToDoubleRegister(instr->value())); | 3954 __ MovToFloatParameter(ToDoubleRegister(instr->value())); |
| 3934 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), | 3955 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), |
| 3935 0, 1); | 3956 0, 1); |
| 3936 __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result())); | 3957 __ MovFromFloatResult(ToDoubleRegister(instr->result())); |
| 3937 } | 3958 } |
| 3938 | 3959 |
| 3939 | 3960 |
| 3940 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3961 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3941 ASSERT(ToRegister(instr->context()).is(cp)); | 3962 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3942 ASSERT(ToRegister(instr->function()).is(r1)); | 3963 ASSERT(ToRegister(instr->function()).is(r1)); |
| 3943 ASSERT(instr->HasPointerMap()); | 3964 ASSERT(instr->HasPointerMap()); |
| 3944 | 3965 |
| 3945 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3966 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3946 if (known_function.is_null()) { | 3967 if (known_function.is_null()) { |
| 3947 LPointerMap* pointers = instr->pointer_map(); | 3968 LPointerMap* pointers = instr->pointer_map(); |
| 3948 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3969 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3949 ParameterCount count(instr->arity()); | 3970 ParameterCount count(instr->arity()); |
| 3950 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3971 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); |
| 3951 } else { | 3972 } else { |
| 3952 CallKnownFunction(known_function, | 3973 CallKnownFunction(known_function, |
| 3953 instr->hydrogen()->formal_parameter_count(), | 3974 instr->hydrogen()->formal_parameter_count(), |
| 3954 instr->arity(), | 3975 instr->arity(), |
| 3955 instr, | 3976 instr, |
| 3956 CALL_AS_METHOD, | 3977 CALL_AS_FUNCTION, |
| 3957 R1_CONTAINS_TARGET); | 3978 R1_CONTAINS_TARGET); |
| 3958 } | 3979 } |
| 3959 } | 3980 } |
| 3960 | 3981 |
| 3961 | 3982 |
| 3962 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 3983 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 3963 ASSERT(ToRegister(instr->context()).is(cp)); | 3984 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3964 ASSERT(ToRegister(instr->result()).is(r0)); | 3985 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3965 | 3986 |
| 3966 int arity = instr->arity(); | 3987 int arity = instr->arity(); |
| 3967 Handle<Code> ic = | 3988 Handle<Code> ic = |
| 3968 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 3989 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
| 3969 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3990 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 3970 } | 3991 } |
| 3971 | 3992 |
| 3972 | 3993 |
| 3973 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 3994 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| 3974 ASSERT(ToRegister(instr->context()).is(cp)); | 3995 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3975 ASSERT(ToRegister(instr->result()).is(r0)); | 3996 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3976 | 3997 |
| 3977 int arity = instr->arity(); | 3998 int arity = instr->arity(); |
| 3978 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | |
| 3979 Handle<Code> ic = | 3999 Handle<Code> ic = |
| 3980 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4000 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); |
| 3981 __ mov(r2, Operand(instr->name())); | 4001 __ mov(r2, Operand(instr->name())); |
| 3982 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4002 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 3983 } | 4003 } |
| 3984 | 4004 |
| 3985 | 4005 |
| 3986 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4006 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 3987 ASSERT(ToRegister(instr->context()).is(cp)); | 4007 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3988 ASSERT(ToRegister(instr->function()).is(r1)); | 4008 ASSERT(ToRegister(instr->function()).is(r1)); |
| 3989 ASSERT(ToRegister(instr->result()).is(r0)); | 4009 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3990 | 4010 |
| 3991 int arity = instr->arity(); | 4011 int arity = instr->arity(); |
| 3992 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4012 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 3993 if (instr->hydrogen()->IsTailCall()) { | 4013 if (instr->hydrogen()->IsTailCall()) { |
| 3994 if (NeedsEagerFrame()) __ mov(sp, fp); | 4014 if (NeedsEagerFrame()) __ mov(sp, fp); |
| 3995 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 4015 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
| 3996 } else { | 4016 } else { |
| 3997 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4017 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3998 } | 4018 } |
| 3999 } | 4019 } |
| 4000 | 4020 |
| 4001 | 4021 |
| 4002 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4022 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 4003 ASSERT(ToRegister(instr->context()).is(cp)); | 4023 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4004 ASSERT(ToRegister(instr->result()).is(r0)); | 4024 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4005 | 4025 |
| 4006 int arity = instr->arity(); | 4026 int arity = instr->arity(); |
| 4007 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | |
| 4008 Handle<Code> ic = | 4027 Handle<Code> ic = |
| 4009 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4028 isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); |
| 4010 __ mov(r2, Operand(instr->name())); | 4029 __ mov(r2, Operand(instr->name())); |
| 4011 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4030 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 4012 } | 4031 } |
| 4013 | 4032 |
| 4014 | 4033 |
| 4015 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 4034 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 4016 ASSERT(ToRegister(instr->result()).is(r0)); | 4035 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4017 CallKnownFunction(instr->hydrogen()->target(), | 4036 CallKnownFunction(instr->hydrogen()->target(), |
| 4018 instr->hydrogen()->formal_parameter_count(), | 4037 instr->hydrogen()->formal_parameter_count(), |
| 4019 instr->arity(), | 4038 instr->arity(), |
| 4020 instr, | 4039 instr, |
| 4021 CALL_AS_FUNCTION, | 4040 CALL_AS_FUNCTION, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4042 ASSERT(ToRegister(instr->constructor()).is(r1)); | 4061 ASSERT(ToRegister(instr->constructor()).is(r1)); |
| 4043 ASSERT(ToRegister(instr->result()).is(r0)); | 4062 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4044 | 4063 |
| 4045 __ mov(r0, Operand(instr->arity())); | 4064 __ mov(r0, Operand(instr->arity())); |
| 4046 __ mov(r2, Operand(instr->hydrogen()->property_cell())); | 4065 __ mov(r2, Operand(instr->hydrogen()->property_cell())); |
| 4047 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4066 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 4048 AllocationSiteOverrideMode override_mode = | 4067 AllocationSiteOverrideMode override_mode = |
| 4049 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4068 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 4050 ? DISABLE_ALLOCATION_SITES | 4069 ? DISABLE_ALLOCATION_SITES |
| 4051 : DONT_OVERRIDE; | 4070 : DONT_OVERRIDE; |
| 4052 ContextCheckMode context_mode = CONTEXT_CHECK_NOT_REQUIRED; | |
| 4053 | 4071 |
| 4054 if (instr->arity() == 0) { | 4072 if (instr->arity() == 0) { |
| 4055 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); | 4073 ArrayNoArgumentConstructorStub stub(kind, override_mode); |
| 4056 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4074 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4057 } else if (instr->arity() == 1) { | 4075 } else if (instr->arity() == 1) { |
| 4058 Label done; | 4076 Label done; |
| 4059 if (IsFastPackedElementsKind(kind)) { | 4077 if (IsFastPackedElementsKind(kind)) { |
| 4060 Label packed_case; | 4078 Label packed_case; |
| 4061 // We might need a change here | 4079 // We might need a change here |
| 4062 // look at the first argument | 4080 // look at the first argument |
| 4063 __ ldr(r5, MemOperand(sp, 0)); | 4081 __ ldr(r5, MemOperand(sp, 0)); |
| 4064 __ cmp(r5, Operand::Zero()); | 4082 __ cmp(r5, Operand::Zero()); |
| 4065 __ b(eq, &packed_case); | 4083 __ b(eq, &packed_case); |
| 4066 | 4084 |
| 4067 ElementsKind holey_kind = GetHoleyElementsKind(kind); | 4085 ElementsKind holey_kind = GetHoleyElementsKind(kind); |
| 4068 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, | 4086 ArraySingleArgumentConstructorStub stub(holey_kind, override_mode); |
| 4069 override_mode); | |
| 4070 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4087 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4071 __ jmp(&done); | 4088 __ jmp(&done); |
| 4072 __ bind(&packed_case); | 4089 __ bind(&packed_case); |
| 4073 } | 4090 } |
| 4074 | 4091 |
| 4075 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); | 4092 ArraySingleArgumentConstructorStub stub(kind, override_mode); |
| 4076 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4093 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4077 __ bind(&done); | 4094 __ bind(&done); |
| 4078 } else { | 4095 } else { |
| 4079 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); | 4096 ArrayNArgumentsConstructorStub stub(kind, override_mode); |
| 4080 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4097 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4081 } | 4098 } |
| 4082 } | 4099 } |
| 4083 | 4100 |
| 4084 | 4101 |
| 4085 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 4102 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 4086 CallRuntime(instr->function(), instr->arity(), instr); | 4103 CallRuntime(instr->function(), instr->arity(), instr); |
| 4087 } | 4104 } |
| 4088 | 4105 |
| 4089 | 4106 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4198 } | 4215 } |
| 4199 | 4216 |
| 4200 | 4217 |
| 4201 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4218 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 4202 ASSERT(ToRegister(instr->context()).is(cp)); | 4219 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4203 ASSERT(ToRegister(instr->object()).is(r1)); | 4220 ASSERT(ToRegister(instr->object()).is(r1)); |
| 4204 ASSERT(ToRegister(instr->value()).is(r0)); | 4221 ASSERT(ToRegister(instr->value()).is(r0)); |
| 4205 | 4222 |
| 4206 // Name is always in r2. | 4223 // Name is always in r2. |
| 4207 __ mov(r2, Operand(instr->name())); | 4224 __ mov(r2, Operand(instr->name())); |
| 4208 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4225 Handle<Code> ic = StoreIC::initialize_stub(isolate(), |
| 4209 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4226 instr->strict_mode_flag(), |
| 4210 : isolate()->builtins()->StoreIC_Initialize(); | 4227 NOT_CONTEXTUAL); |
| 4211 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4228 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
| 4212 } | 4229 } |
| 4213 | 4230 |
| 4214 | 4231 |
| 4215 void LCodeGen::ApplyCheckIf(Condition condition, LBoundsCheck* check) { | 4232 void LCodeGen::ApplyCheckIf(Condition condition, LBoundsCheck* check) { |
| 4216 if (FLAG_debug_code && check->hydrogen()->skip_check()) { | 4233 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
| 4217 Label done; | 4234 Label done; |
| 4218 __ b(NegateCondition(condition), &done); | 4235 __ b(NegateCondition(condition), &done); |
| 4219 __ stop("eliminated bounds check failed"); | 4236 __ stop("eliminated bounds check failed"); |
| 4220 __ bind(&done); | 4237 __ bind(&done); |
| (...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5807 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5824 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5808 __ ldr(result, FieldMemOperand(scratch, | 5825 __ ldr(result, FieldMemOperand(scratch, |
| 5809 FixedArray::kHeaderSize - kPointerSize)); | 5826 FixedArray::kHeaderSize - kPointerSize)); |
| 5810 __ bind(&done); | 5827 __ bind(&done); |
| 5811 } | 5828 } |
| 5812 | 5829 |
| 5813 | 5830 |
| 5814 #undef __ | 5831 #undef __ |
| 5815 | 5832 |
| 5816 } } // namespace v8::internal | 5833 } } // namespace v8::internal |
| OLD | NEW |