| 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 descriptor->register_param_count_ = 4; | 98 descriptor->register_param_count_ = 4; |
| 99 descriptor->register_params_ = registers; | 99 descriptor->register_params_ = registers; |
| 100 descriptor->deoptimization_handler_ = | 100 descriptor->deoptimization_handler_ = |
| 101 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry; | 101 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry; |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( | 105 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
| 106 Isolate* isolate, | 106 Isolate* isolate, |
| 107 CodeStubInterfaceDescriptor* descriptor) { | 107 CodeStubInterfaceDescriptor* descriptor) { |
| 108 static Register registers[] = { r2, r3 }; | 108 static Register registers[] = { r2 }; |
| 109 descriptor->register_param_count_ = 2; | 109 descriptor->register_param_count_ = 1; |
| 110 descriptor->register_params_ = registers; | 110 descriptor->register_params_ = registers; |
| 111 descriptor->deoptimization_handler_ = NULL; | 111 descriptor->deoptimization_handler_ = NULL; |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 115 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
| 116 Isolate* isolate, | 116 Isolate* isolate, |
| 117 CodeStubInterfaceDescriptor* descriptor) { | 117 CodeStubInterfaceDescriptor* descriptor) { |
| 118 static Register registers[] = { r1, r0 }; | 118 static Register registers[] = { r1, r0 }; |
| 119 descriptor->register_param_count_ = 2; | 119 descriptor->register_param_count_ = 2; |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 exponent, | 595 exponent, |
| 596 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); | 596 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); |
| 597 __ Ret(); | 597 __ Ret(); |
| 598 } | 598 } |
| 599 | 599 |
| 600 | 600 |
| 601 void DoubleToIStub::Generate(MacroAssembler* masm) { | 601 void DoubleToIStub::Generate(MacroAssembler* masm) { |
| 602 Label out_of_range, only_low, negate, done; | 602 Label out_of_range, only_low, negate, done; |
| 603 Register input_reg = source(); | 603 Register input_reg = source(); |
| 604 Register result_reg = destination(); | 604 Register result_reg = destination(); |
| 605 ASSERT(is_truncating()); | |
| 606 | 605 |
| 607 int double_offset = offset(); | 606 int double_offset = offset(); |
| 608 // Account for saved regs if input is sp. | 607 // Account for saved regs if input is sp. |
| 609 if (input_reg.is(sp)) double_offset += 3 * kPointerSize; | 608 if (input_reg.is(sp)) double_offset += 3 * kPointerSize; |
| 610 | 609 |
| 611 Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg); | 610 Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg); |
| 612 Register scratch_low = | 611 Register scratch_low = |
| 613 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch); | 612 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch); |
| 614 Register scratch_high = | 613 Register scratch_high = |
| 615 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low); | 614 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low); |
| (...skipping 2382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2998 // Load offset into r9 and replace subject string with parent. | 2997 // Load offset into r9 and replace subject string with parent. |
| 2999 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | 2998 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 3000 __ SmiUntag(r9); | 2999 __ SmiUntag(r9); |
| 3001 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 3000 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 3002 __ jmp(&check_underlying); // Go to (4). | 3001 __ jmp(&check_underlying); // Go to (4). |
| 3003 #endif // V8_INTERPRETED_REGEXP | 3002 #endif // V8_INTERPRETED_REGEXP |
| 3004 } | 3003 } |
| 3005 | 3004 |
| 3006 | 3005 |
| 3007 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 3006 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
| 3008 // Cache the called function in a feedback vector slot. Cache states | 3007 // Cache the called function in a global property cell. Cache states |
| 3009 // are uninitialized, monomorphic (indicated by a JSFunction), and | 3008 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 3010 // megamorphic. | 3009 // megamorphic. |
| 3011 // r0 : number of arguments to the construct function | 3010 // r0 : number of arguments to the construct function |
| 3012 // r1 : the function to call | 3011 // r1 : the function to call |
| 3013 // r2 : Feedback vector | 3012 // r2 : cache cell for call target |
| 3014 // r3 : slot in feedback vector (Smi) | |
| 3015 Label initialize, done, miss, megamorphic, not_array_function; | 3013 Label initialize, done, miss, megamorphic, not_array_function; |
| 3016 | 3014 |
| 3017 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3015 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), |
| 3018 masm->isolate()->heap()->undefined_value()); | 3016 masm->isolate()->heap()->undefined_value()); |
| 3019 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), | 3017 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), |
| 3020 masm->isolate()->heap()->the_hole_value()); | 3018 masm->isolate()->heap()->the_hole_value()); |
| 3021 | 3019 |
| 3022 // Load the cache state into r4. | 3020 // Load the cache state into r3. |
| 3023 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 3021 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); |
| 3024 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); | |
| 3025 | 3022 |
| 3026 // A monomorphic cache hit or an already megamorphic state: invoke the | 3023 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 3027 // function without changing the state. | 3024 // function without changing the state. |
| 3028 __ cmp(r4, r1); | 3025 __ cmp(r3, r1); |
| 3029 __ b(eq, &done); | 3026 __ b(eq, &done); |
| 3030 | 3027 |
| 3031 // If we came here, we need to see if we are the array function. | 3028 // If we came here, we need to see if we are the array function. |
| 3032 // If we didn't have a matching function, and we didn't find the megamorph | 3029 // If we didn't have a matching function, and we didn't find the megamorph |
| 3033 // sentinel, then we have in the slot either some other function or an | 3030 // sentinel, then we have in the cell either some other function or an |
| 3034 // AllocationSite. Do a map check on the object in ecx. | 3031 // AllocationSite. Do a map check on the object in ecx. |
| 3035 __ ldr(r5, FieldMemOperand(r4, 0)); | 3032 __ ldr(r5, FieldMemOperand(r3, 0)); |
| 3036 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); | 3033 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); |
| 3037 __ b(ne, &miss); | 3034 __ b(ne, &miss); |
| 3038 | 3035 |
| 3039 // Make sure the function is the Array() function | 3036 // Make sure the function is the Array() function |
| 3040 __ LoadArrayFunction(r4); | 3037 __ LoadArrayFunction(r3); |
| 3041 __ cmp(r1, r4); | 3038 __ cmp(r1, r3); |
| 3042 __ b(ne, &megamorphic); | 3039 __ b(ne, &megamorphic); |
| 3043 __ jmp(&done); | 3040 __ jmp(&done); |
| 3044 | 3041 |
| 3045 __ bind(&miss); | 3042 __ bind(&miss); |
| 3046 | 3043 |
| 3047 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3044 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 3048 // megamorphic. | 3045 // megamorphic. |
| 3049 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); | 3046 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 3050 __ b(eq, &initialize); | 3047 __ b(eq, &initialize); |
| 3051 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3048 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 3052 // write-barrier is needed. | 3049 // write-barrier is needed. |
| 3053 __ bind(&megamorphic); | 3050 __ bind(&megamorphic); |
| 3054 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | |
| 3055 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 3051 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 3056 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); | 3052 __ str(ip, FieldMemOperand(r2, Cell::kValueOffset)); |
| 3057 __ jmp(&done); | 3053 __ jmp(&done); |
| 3058 | 3054 |
| 3059 // An uninitialized cache is patched with the function or sentinel to | 3055 // An uninitialized cache is patched with the function or sentinel to |
| 3060 // indicate the ElementsKind if function is the Array constructor. | 3056 // indicate the ElementsKind if function is the Array constructor. |
| 3061 __ bind(&initialize); | 3057 __ bind(&initialize); |
| 3062 // Make sure the function is the Array() function | 3058 // Make sure the function is the Array() function |
| 3063 __ LoadArrayFunction(r4); | 3059 __ LoadArrayFunction(r3); |
| 3064 __ cmp(r1, r4); | 3060 __ cmp(r1, r3); |
| 3065 __ b(ne, ¬_array_function); | 3061 __ b(ne, ¬_array_function); |
| 3066 | 3062 |
| 3067 // The target function is the Array constructor, | 3063 // The target function is the Array constructor, |
| 3068 // Create an AllocationSite if we don't already have it, store it in the slot. | 3064 // Create an AllocationSite if we don't already have it, store it in the cell |
| 3069 { | 3065 { |
| 3070 FrameScope scope(masm, StackFrame::INTERNAL); | 3066 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3071 | 3067 |
| 3072 // Arguments register must be smi-tagged to call out. | 3068 // Arguments register must be smi-tagged to call out. |
| 3073 __ SmiTag(r0); | 3069 __ SmiTag(r0); |
| 3074 __ Push(r3, r2, r1, r0); | 3070 __ Push(r2, r1, r0); |
| 3075 | 3071 |
| 3076 CreateAllocationSiteStub create_stub; | 3072 CreateAllocationSiteStub create_stub; |
| 3077 __ CallStub(&create_stub); | 3073 __ CallStub(&create_stub); |
| 3078 | 3074 |
| 3079 __ Pop(r3, r2, r1, r0); | 3075 __ Pop(r2, r1, r0); |
| 3080 __ SmiUntag(r0); | 3076 __ SmiUntag(r0); |
| 3081 } | 3077 } |
| 3082 __ b(&done); | 3078 __ b(&done); |
| 3083 | 3079 |
| 3084 __ bind(¬_array_function); | 3080 __ bind(¬_array_function); |
| 3085 | 3081 __ str(r1, FieldMemOperand(r2, Cell::kValueOffset)); |
| 3086 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 3082 // No need for a write barrier here - cells are rescanned. |
| 3087 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | |
| 3088 __ str(r1, MemOperand(r4, 0)); | |
| 3089 | |
| 3090 __ Push(r4, r2, r1); | |
| 3091 __ RecordWrite(r2, r4, r1, kLRHasNotBeenSaved, kDontSaveFPRegs, | |
| 3092 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
| 3093 __ Pop(r4, r2, r1); | |
| 3094 | 3083 |
| 3095 __ bind(&done); | 3084 __ bind(&done); |
| 3096 } | 3085 } |
| 3097 | 3086 |
| 3098 | 3087 |
| 3099 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3088 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3100 // r1 : the function to call | 3089 // r1 : the function to call |
| 3101 // r2 : feedback vector | 3090 // r2 : cache cell for call target |
| 3102 // r3 : (only if r2 is not undefined) slot in feedback vector (Smi) | |
| 3103 Label slow, non_function, wrap, cont; | 3091 Label slow, non_function, wrap, cont; |
| 3104 | 3092 |
| 3105 if (NeedsChecks()) { | 3093 if (NeedsChecks()) { |
| 3106 // Check that the function is really a JavaScript function. | 3094 // Check that the function is really a JavaScript function. |
| 3107 // r1: pushed function (to be verified) | 3095 // r1: pushed function (to be verified) |
| 3108 __ JumpIfSmi(r1, &non_function); | 3096 __ JumpIfSmi(r1, &non_function); |
| 3109 | 3097 |
| 3110 // Goto slow case if we do not have a function. | 3098 // Goto slow case if we do not have a function. |
| 3111 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 3099 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 3112 __ b(ne, &slow); | 3100 __ b(ne, &slow); |
| 3113 | 3101 |
| 3114 if (RecordCallTarget()) { | 3102 if (RecordCallTarget()) { |
| 3115 GenerateRecordCallTarget(masm); | 3103 GenerateRecordCallTarget(masm); |
| 3116 } | 3104 } |
| 3117 } | 3105 } |
| 3118 | 3106 |
| 3119 // Fast-case: Invoke the function now. | 3107 // Fast-case: Invoke the function now. |
| 3120 // r1: pushed function | 3108 // r1: pushed function |
| 3121 ParameterCount actual(argc_); | 3109 ParameterCount actual(argc_); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3149 } | 3137 } |
| 3150 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); | 3138 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 3151 | 3139 |
| 3152 if (NeedsChecks()) { | 3140 if (NeedsChecks()) { |
| 3153 // Slow-case: Non-function called. | 3141 // Slow-case: Non-function called. |
| 3154 __ bind(&slow); | 3142 __ bind(&slow); |
| 3155 if (RecordCallTarget()) { | 3143 if (RecordCallTarget()) { |
| 3156 // If there is a call target cache, mark it megamorphic in the | 3144 // If there is a call target cache, mark it megamorphic in the |
| 3157 // non-function case. MegamorphicSentinel is an immortal immovable | 3145 // non-function case. MegamorphicSentinel is an immortal immovable |
| 3158 // object (undefined) so no write barrier is needed. | 3146 // object (undefined) so no write barrier is needed. |
| 3159 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3147 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), |
| 3160 masm->isolate()->heap()->undefined_value()); | 3148 masm->isolate()->heap()->undefined_value()); |
| 3161 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); | |
| 3162 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 3149 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 3163 __ str(ip, FieldMemOperand(r5, FixedArray::kHeaderSize)); | 3150 __ str(ip, FieldMemOperand(r2, Cell::kValueOffset)); |
| 3164 } | 3151 } |
| 3165 // Check for function proxy. | 3152 // Check for function proxy. |
| 3166 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); | 3153 __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 3167 __ b(ne, &non_function); | 3154 __ b(ne, &non_function); |
| 3168 __ push(r1); // put proxy as additional argument | 3155 __ push(r1); // put proxy as additional argument |
| 3169 __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32)); | 3156 __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32)); |
| 3170 __ mov(r2, Operand::Zero()); | 3157 __ mov(r2, Operand::Zero()); |
| 3171 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); | 3158 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); |
| 3172 { | 3159 { |
| 3173 Handle<Code> adaptor = | 3160 Handle<Code> adaptor = |
| 3174 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3161 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3175 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3162 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3176 } | 3163 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3196 } | 3183 } |
| 3197 __ str(r0, MemOperand(sp, argc_ * kPointerSize)); | 3184 __ str(r0, MemOperand(sp, argc_ * kPointerSize)); |
| 3198 __ jmp(&cont); | 3185 __ jmp(&cont); |
| 3199 } | 3186 } |
| 3200 } | 3187 } |
| 3201 | 3188 |
| 3202 | 3189 |
| 3203 void CallConstructStub::Generate(MacroAssembler* masm) { | 3190 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 3204 // r0 : number of arguments | 3191 // r0 : number of arguments |
| 3205 // r1 : the function to call | 3192 // r1 : the function to call |
| 3206 // r2 : feedback vector | 3193 // r2 : cache cell for call target |
| 3207 // r3 : (only if r2 is not undefined) slot in feedback vector (Smi) | |
| 3208 Label slow, non_function_call; | 3194 Label slow, non_function_call; |
| 3209 | 3195 |
| 3210 // Check that the function is not a smi. | 3196 // Check that the function is not a smi. |
| 3211 __ JumpIfSmi(r1, &non_function_call); | 3197 __ JumpIfSmi(r1, &non_function_call); |
| 3212 // Check that the function is a JSFunction. | 3198 // Check that the function is a JSFunction. |
| 3213 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 3199 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 3214 __ b(ne, &slow); | 3200 __ b(ne, &slow); |
| 3215 | 3201 |
| 3216 if (RecordCallTarget()) { | 3202 if (RecordCallTarget()) { |
| 3217 GenerateRecordCallTarget(masm); | 3203 GenerateRecordCallTarget(masm); |
| 3218 } | 3204 } |
| 3219 | 3205 |
| 3220 // Jump to the function-specific construct stub. | 3206 // Jump to the function-specific construct stub. |
| 3221 Register jmp_reg = r4; | 3207 Register jmp_reg = r3; |
| 3222 __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 3208 __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 3223 __ ldr(jmp_reg, FieldMemOperand(jmp_reg, | 3209 __ ldr(jmp_reg, FieldMemOperand(jmp_reg, |
| 3224 SharedFunctionInfo::kConstructStubOffset)); | 3210 SharedFunctionInfo::kConstructStubOffset)); |
| 3225 __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); | 3211 __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 3226 | 3212 |
| 3227 // r0: number of arguments | 3213 // r0: number of arguments |
| 3228 // r1: called object | 3214 // r1: called object |
| 3229 // r4: object type | 3215 // r3: object type |
| 3230 Label do_call; | 3216 Label do_call; |
| 3231 __ bind(&slow); | 3217 __ bind(&slow); |
| 3232 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); | 3218 __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 3233 __ b(ne, &non_function_call); | 3219 __ b(ne, &non_function_call); |
| 3234 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 3220 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
| 3235 __ jmp(&do_call); | 3221 __ jmp(&do_call); |
| 3236 | 3222 |
| 3237 __ bind(&non_function_call); | 3223 __ bind(&non_function_call); |
| 3238 __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 3224 __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 3239 __ bind(&do_call); | 3225 __ bind(&do_call); |
| 3240 // Set expected number of arguments to zero (not changing r0). | 3226 // Set expected number of arguments to zero (not changing r0). |
| 3241 __ mov(r2, Operand::Zero()); | 3227 __ mov(r2, Operand::Zero()); |
| 3242 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3228 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| (...skipping 1939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5182 ArraySingleArgumentConstructorStub stub_holey(holey_initial, | 5168 ArraySingleArgumentConstructorStub stub_holey(holey_initial, |
| 5183 DISABLE_ALLOCATION_SITES); | 5169 DISABLE_ALLOCATION_SITES); |
| 5184 __ TailCallStub(&stub_holey); | 5170 __ TailCallStub(&stub_holey); |
| 5185 | 5171 |
| 5186 __ bind(&normal_sequence); | 5172 __ bind(&normal_sequence); |
| 5187 ArraySingleArgumentConstructorStub stub(initial, | 5173 ArraySingleArgumentConstructorStub stub(initial, |
| 5188 DISABLE_ALLOCATION_SITES); | 5174 DISABLE_ALLOCATION_SITES); |
| 5189 __ TailCallStub(&stub); | 5175 __ TailCallStub(&stub); |
| 5190 } else if (mode == DONT_OVERRIDE) { | 5176 } else if (mode == DONT_OVERRIDE) { |
| 5191 // We are going to create a holey array, but our kind is non-holey. | 5177 // We are going to create a holey array, but our kind is non-holey. |
| 5192 // Fix kind and retry (only if we have an allocation site in the slot). | 5178 // Fix kind and retry (only if we have an allocation site in the cell). |
| 5193 __ add(r3, r3, Operand(1)); | 5179 __ add(r3, r3, Operand(1)); |
| 5194 | 5180 |
| 5195 if (FLAG_debug_code) { | 5181 if (FLAG_debug_code) { |
| 5196 __ ldr(r5, FieldMemOperand(r2, 0)); | 5182 __ ldr(r5, FieldMemOperand(r2, 0)); |
| 5197 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); | 5183 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); |
| 5198 __ Assert(eq, kExpectedAllocationSite); | 5184 __ Assert(eq, kExpectedAllocationSite); |
| 5199 } | 5185 } |
| 5200 | 5186 |
| 5201 // Save the resulting elements kind in type info. We can't just store r3 | 5187 // Save the resulting elements kind in type info. We can't just store r3 |
| 5202 // in the AllocationSite::transition_info field because elements kind is | 5188 // in the AllocationSite::transition_info field because elements kind is |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5290 } else { | 5276 } else { |
| 5291 UNREACHABLE(); | 5277 UNREACHABLE(); |
| 5292 } | 5278 } |
| 5293 } | 5279 } |
| 5294 | 5280 |
| 5295 | 5281 |
| 5296 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5282 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5297 // ----------- S t a t e ------------- | 5283 // ----------- S t a t e ------------- |
| 5298 // -- r0 : argc (only if argument_count_ == ANY) | 5284 // -- r0 : argc (only if argument_count_ == ANY) |
| 5299 // -- r1 : constructor | 5285 // -- r1 : constructor |
| 5300 // -- r2 : feedback vector (fixed array or undefined) | 5286 // -- r2 : type info cell |
| 5301 // -- r3 : slot index (if r2 is fixed array) | |
| 5302 // -- sp[0] : return address | 5287 // -- sp[0] : return address |
| 5303 // -- sp[4] : last argument | 5288 // -- sp[4] : last argument |
| 5304 // ----------------------------------- | 5289 // ----------------------------------- |
| 5305 if (FLAG_debug_code) { | 5290 if (FLAG_debug_code) { |
| 5306 // The array construct code is only set for the global and natives | 5291 // The array construct code is only set for the global and natives |
| 5307 // builtin Array functions which always have maps. | 5292 // builtin Array functions which always have maps. |
| 5308 | 5293 |
| 5309 // Initial map for the builtin Array function should be a map. | 5294 // Initial map for the builtin Array function should be a map. |
| 5310 __ ldr(r4, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 5295 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 5311 // Will both indicate a NULL and a Smi. | 5296 // Will both indicate a NULL and a Smi. |
| 5312 __ tst(r4, Operand(kSmiTagMask)); | 5297 __ tst(r3, Operand(kSmiTagMask)); |
| 5313 __ Assert(ne, kUnexpectedInitialMapForArrayFunction); | 5298 __ Assert(ne, kUnexpectedInitialMapForArrayFunction); |
| 5314 __ CompareObjectType(r4, r4, r5, MAP_TYPE); | 5299 __ CompareObjectType(r3, r3, r4, MAP_TYPE); |
| 5315 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); | 5300 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); |
| 5316 | 5301 |
| 5317 // We should either have undefined in ebx or a valid fixed array. | 5302 // We should either have undefined in ebx or a valid cell |
| 5318 Label okay_here; | 5303 Label okay_here; |
| 5319 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); | 5304 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
| 5320 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); | 5305 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 5321 __ b(eq, &okay_here); | 5306 __ b(eq, &okay_here); |
| 5322 __ ldr(r4, FieldMemOperand(r2, 0)); | 5307 __ ldr(r3, FieldMemOperand(r2, 0)); |
| 5323 __ cmp(r4, Operand(fixed_array_map)); | 5308 __ cmp(r3, Operand(cell_map)); |
| 5324 __ Assert(eq, kExpectedFixedArrayInRegisterR2); | 5309 __ Assert(eq, kExpectedPropertyCellInRegisterEbx); |
| 5325 | |
| 5326 // r3 should be a smi if we don't have undefined in r2 | |
| 5327 __ AssertSmi(r3); | |
| 5328 | |
| 5329 __ bind(&okay_here); | 5310 __ bind(&okay_here); |
| 5330 } | 5311 } |
| 5331 | 5312 |
| 5332 Label no_info; | 5313 Label no_info; |
| 5333 // Get the elements kind and case on that. | 5314 // Get the elements kind and case on that. |
| 5334 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); | 5315 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 5335 __ b(eq, &no_info); | 5316 __ b(eq, &no_info); |
| 5336 __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); | 5317 __ ldr(r2, FieldMemOperand(r2, Cell::kValueOffset)); |
| 5337 __ ldr(r2, FieldMemOperand(r2, FixedArray::kHeaderSize)); | |
| 5338 | 5318 |
| 5339 // If the feedback vector is undefined, or contains anything other than an | 5319 // If the type cell is undefined, or contains anything other than an |
| 5340 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 5320 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
| 5341 __ ldr(r4, FieldMemOperand(r2, 0)); | 5321 __ ldr(r4, FieldMemOperand(r2, 0)); |
| 5342 __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex); | 5322 __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex); |
| 5343 __ b(ne, &no_info); | 5323 __ b(ne, &no_info); |
| 5344 | 5324 |
| 5345 __ ldr(r3, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset)); | 5325 __ ldr(r3, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset)); |
| 5346 __ SmiUntag(r3); | 5326 __ SmiUntag(r3); |
| 5347 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 5327 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
| 5348 __ and_(r3, r3, Operand(AllocationSite::ElementsKindBits::kMask)); | 5328 __ and_(r3, r3, Operand(AllocationSite::ElementsKindBits::kMask)); |
| 5349 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 5329 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5442 // -- sp[argc * 4] : receiver | 5422 // -- sp[argc * 4] : receiver |
| 5443 // ----------------------------------- | 5423 // ----------------------------------- |
| 5444 | 5424 |
| 5445 Register callee = r0; | 5425 Register callee = r0; |
| 5446 Register call_data = r4; | 5426 Register call_data = r4; |
| 5447 Register holder = r2; | 5427 Register holder = r2; |
| 5448 Register api_function_address = r1; | 5428 Register api_function_address = r1; |
| 5449 Register context = cp; | 5429 Register context = cp; |
| 5450 | 5430 |
| 5451 int argc = ArgumentBits::decode(bit_field_); | 5431 int argc = ArgumentBits::decode(bit_field_); |
| 5452 bool is_store = IsStoreBits::decode(bit_field_); | 5432 bool restore_context = RestoreContextBits::decode(bit_field_); |
| 5453 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 5433 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); |
| 5454 | 5434 |
| 5455 typedef FunctionCallbackArguments FCA; | 5435 typedef FunctionCallbackArguments FCA; |
| 5456 | 5436 |
| 5457 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 5437 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 5458 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 5438 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 5459 STATIC_ASSERT(FCA::kDataIndex == 4); | 5439 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 5460 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 5440 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 5461 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 5441 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 5462 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 5442 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5520 const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; | 5500 const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; |
| 5521 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); | 5501 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
| 5522 ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; | 5502 ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; |
| 5523 ApiFunction thunk_fun(thunk_address); | 5503 ApiFunction thunk_fun(thunk_address); |
| 5524 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, | 5504 ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, |
| 5525 masm->isolate()); | 5505 masm->isolate()); |
| 5526 | 5506 |
| 5527 AllowExternalCallThatCantCauseGC scope(masm); | 5507 AllowExternalCallThatCantCauseGC scope(masm); |
| 5528 MemOperand context_restore_operand( | 5508 MemOperand context_restore_operand( |
| 5529 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); | 5509 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); |
| 5530 // Stores return the first js argument | 5510 MemOperand return_value_operand(fp, |
| 5531 int return_value_offset = 0; | 5511 (2 + FCA::kReturnValueOffset) * kPointerSize); |
| 5532 if (is_store) { | |
| 5533 return_value_offset = 2 + FCA::kArgsLength; | |
| 5534 } else { | |
| 5535 return_value_offset = 2 + FCA::kReturnValueOffset; | |
| 5536 } | |
| 5537 MemOperand return_value_operand(fp, return_value_offset * kPointerSize); | |
| 5538 | 5512 |
| 5539 __ CallApiFunctionAndReturn(api_function_address, | 5513 __ CallApiFunctionAndReturn(api_function_address, |
| 5540 thunk_ref, | 5514 thunk_ref, |
| 5541 kStackUnwindSpace, | 5515 kStackUnwindSpace, |
| 5542 return_value_operand, | 5516 return_value_operand, |
| 5543 &context_restore_operand); | 5517 restore_context ? |
| 5518 &context_restore_operand : NULL); |
| 5544 } | 5519 } |
| 5545 | 5520 |
| 5546 | 5521 |
| 5547 void CallApiGetterStub::Generate(MacroAssembler* masm) { | 5522 void CallApiGetterStub::Generate(MacroAssembler* masm) { |
| 5548 // ----------- S t a t e ------------- | 5523 // ----------- S t a t e ------------- |
| 5549 // -- sp[0] : name | 5524 // -- sp[0] : name |
| 5550 // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object | 5525 // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object |
| 5551 // -- ... | 5526 // -- ... |
| 5552 // -- r2 : api_function_address | 5527 // -- r2 : api_function_address |
| 5553 // ----------------------------------- | 5528 // ----------------------------------- |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5580 MemOperand(fp, 6 * kPointerSize), | 5555 MemOperand(fp, 6 * kPointerSize), |
| 5581 NULL); | 5556 NULL); |
| 5582 } | 5557 } |
| 5583 | 5558 |
| 5584 | 5559 |
| 5585 #undef __ | 5560 #undef __ |
| 5586 | 5561 |
| 5587 } } // namespace v8::internal | 5562 } } // namespace v8::internal |
| 5588 | 5563 |
| 5589 #endif // V8_TARGET_ARCH_ARM | 5564 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |