| 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 2997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3008 // Cache the called function in a feedback vector slot. Cache states | 3008 // Cache the called function in a feedback vector slot. Cache states |
| 3009 // are uninitialized, monomorphic (indicated by a JSFunction), and | 3009 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 3010 // megamorphic. | 3010 // megamorphic. |
| 3011 // r0 : number of arguments to the construct function | 3011 // r0 : number of arguments to the construct function |
| 3012 // r1 : the function to call | 3012 // r1 : the function to call |
| 3013 // r2 : Feedback vector | 3013 // r2 : Feedback vector |
| 3014 // r3 : slot in feedback vector (Smi) | 3014 // r3 : slot in feedback vector (Smi) |
| 3015 Label initialize, done, miss, megamorphic, not_array_function; | 3015 Label initialize, done, miss, megamorphic, not_array_function; |
| 3016 | 3016 |
| 3017 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3017 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
| 3018 masm->isolate()->heap()->undefined_value()); | 3018 masm->isolate()->heap()->megamorphic_symbol()); |
| 3019 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), | 3019 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), |
| 3020 masm->isolate()->heap()->the_hole_value()); | 3020 masm->isolate()->heap()->uninitialized_symbol()); |
| 3021 | 3021 |
| 3022 // Load the cache state into r4. | 3022 // Load the cache state into r4. |
| 3023 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 3023 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 3024 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); | 3024 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); |
| 3025 | 3025 |
| 3026 // A monomorphic cache hit or an already megamorphic state: invoke the | 3026 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 3027 // function without changing the state. | 3027 // function without changing the state. |
| 3028 __ cmp(r4, r1); | 3028 __ cmp(r4, r1); |
| 3029 __ b(eq, &done); | 3029 __ b(eq, &done); |
| 3030 | 3030 |
| 3031 // If we came here, we need to see if we are the array function. | 3031 // 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 | 3032 // 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 | 3033 // sentinel, then we have in the slot either some other function or an |
| 3034 // AllocationSite. Do a map check on the object in ecx. | 3034 // AllocationSite. Do a map check on the object in ecx. |
| 3035 __ ldr(r5, FieldMemOperand(r4, 0)); | 3035 __ ldr(r5, FieldMemOperand(r4, 0)); |
| 3036 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); | 3036 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); |
| 3037 __ b(ne, &miss); | 3037 __ b(ne, &miss); |
| 3038 | 3038 |
| 3039 // Make sure the function is the Array() function | 3039 // Make sure the function is the Array() function |
| 3040 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); | 3040 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); |
| 3041 __ cmp(r1, r4); | 3041 __ cmp(r1, r4); |
| 3042 __ b(ne, &megamorphic); | 3042 __ b(ne, &megamorphic); |
| 3043 __ jmp(&done); | 3043 __ jmp(&done); |
| 3044 | 3044 |
| 3045 __ bind(&miss); | 3045 __ bind(&miss); |
| 3046 | 3046 |
| 3047 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3047 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 3048 // megamorphic. | 3048 // megamorphic. |
| 3049 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); | 3049 __ CompareRoot(r4, Heap::kUninitializedSymbolRootIndex); |
| 3050 __ b(eq, &initialize); | 3050 __ b(eq, &initialize); |
| 3051 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3051 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 3052 // write-barrier is needed. | 3052 // write-barrier is needed. |
| 3053 __ bind(&megamorphic); | 3053 __ bind(&megamorphic); |
| 3054 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 3054 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 3055 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 3055 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); |
| 3056 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); | 3056 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); |
| 3057 __ jmp(&done); | 3057 __ jmp(&done); |
| 3058 | 3058 |
| 3059 // An uninitialized cache is patched with the function or sentinel to | 3059 // An uninitialized cache is patched with the function or sentinel to |
| 3060 // indicate the ElementsKind if function is the Array constructor. | 3060 // indicate the ElementsKind if function is the Array constructor. |
| 3061 __ bind(&initialize); | 3061 __ bind(&initialize); |
| 3062 // Make sure the function is the Array() function | 3062 // Make sure the function is the Array() function |
| 3063 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); | 3063 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); |
| 3064 __ cmp(r1, r4); | 3064 __ cmp(r1, r4); |
| 3065 __ b(ne, ¬_array_function); | 3065 __ b(ne, ¬_array_function); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3092 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 3092 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 3093 __ Pop(r4, r2, r1); | 3093 __ Pop(r4, r2, r1); |
| 3094 | 3094 |
| 3095 __ bind(&done); | 3095 __ bind(&done); |
| 3096 } | 3096 } |
| 3097 | 3097 |
| 3098 | 3098 |
| 3099 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3099 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3100 // r1 : the function to call | 3100 // r1 : the function to call |
| 3101 // r2 : feedback vector | 3101 // r2 : feedback vector |
| 3102 // r3 : (only if r2 is not undefined) slot in feedback vector (Smi) | 3102 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback |
| 3103 // vector (Smi) |
| 3103 Label slow, non_function, wrap, cont; | 3104 Label slow, non_function, wrap, cont; |
| 3104 | 3105 |
| 3105 if (NeedsChecks()) { | 3106 if (NeedsChecks()) { |
| 3106 // Check that the function is really a JavaScript function. | 3107 // Check that the function is really a JavaScript function. |
| 3107 // r1: pushed function (to be verified) | 3108 // r1: pushed function (to be verified) |
| 3108 __ JumpIfSmi(r1, &non_function); | 3109 __ JumpIfSmi(r1, &non_function); |
| 3109 | 3110 |
| 3110 // Goto slow case if we do not have a function. | 3111 // Goto slow case if we do not have a function. |
| 3111 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 3112 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |
| 3112 __ b(ne, &slow); | 3113 __ b(ne, &slow); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3148 __ bind(&cont); | 3149 __ bind(&cont); |
| 3149 } | 3150 } |
| 3150 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); | 3151 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 3151 | 3152 |
| 3152 if (NeedsChecks()) { | 3153 if (NeedsChecks()) { |
| 3153 // Slow-case: Non-function called. | 3154 // Slow-case: Non-function called. |
| 3154 __ bind(&slow); | 3155 __ bind(&slow); |
| 3155 if (RecordCallTarget()) { | 3156 if (RecordCallTarget()) { |
| 3156 // If there is a call target cache, mark it megamorphic in the | 3157 // If there is a call target cache, mark it megamorphic in the |
| 3157 // non-function case. MegamorphicSentinel is an immortal immovable | 3158 // non-function case. MegamorphicSentinel is an immortal immovable |
| 3158 // object (undefined) so no write barrier is needed. | 3159 // object (megamorphic symbol) so no write barrier is needed. |
| 3159 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3160 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
| 3160 masm->isolate()->heap()->undefined_value()); | 3161 masm->isolate()->heap()->megamorphic_symbol()); |
| 3161 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); | 3162 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 3162 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 3163 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); |
| 3163 __ str(ip, FieldMemOperand(r5, FixedArray::kHeaderSize)); | 3164 __ str(ip, FieldMemOperand(r5, FixedArray::kHeaderSize)); |
| 3164 } | 3165 } |
| 3165 // Check for function proxy. | 3166 // Check for function proxy. |
| 3166 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); | 3167 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 3167 __ b(ne, &non_function); | 3168 __ b(ne, &non_function); |
| 3168 __ push(r1); // put proxy as additional argument | 3169 __ push(r1); // put proxy as additional argument |
| 3169 __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32)); | 3170 __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32)); |
| 3170 __ mov(r2, Operand::Zero()); | 3171 __ mov(r2, Operand::Zero()); |
| 3171 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); | 3172 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); |
| 3172 { | 3173 { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3197 __ str(r0, MemOperand(sp, argc_ * kPointerSize)); | 3198 __ str(r0, MemOperand(sp, argc_ * kPointerSize)); |
| 3198 __ jmp(&cont); | 3199 __ jmp(&cont); |
| 3199 } | 3200 } |
| 3200 } | 3201 } |
| 3201 | 3202 |
| 3202 | 3203 |
| 3203 void CallConstructStub::Generate(MacroAssembler* masm) { | 3204 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 3204 // r0 : number of arguments | 3205 // r0 : number of arguments |
| 3205 // r1 : the function to call | 3206 // r1 : the function to call |
| 3206 // r2 : feedback vector | 3207 // r2 : feedback vector |
| 3207 // r3 : (only if r2 is not undefined) slot in feedback vector (Smi) | 3208 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback |
| 3209 // vector (Smi) |
| 3208 Label slow, non_function_call; | 3210 Label slow, non_function_call; |
| 3209 | 3211 |
| 3210 // Check that the function is not a smi. | 3212 // Check that the function is not a smi. |
| 3211 __ JumpIfSmi(r1, &non_function_call); | 3213 __ JumpIfSmi(r1, &non_function_call); |
| 3212 // Check that the function is a JSFunction. | 3214 // Check that the function is a JSFunction. |
| 3213 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 3215 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |
| 3214 __ b(ne, &slow); | 3216 __ b(ne, &slow); |
| 3215 | 3217 |
| 3216 if (RecordCallTarget()) { | 3218 if (RecordCallTarget()) { |
| 3217 GenerateRecordCallTarget(masm); | 3219 GenerateRecordCallTarget(masm); |
| (...skipping 2072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5290 } else { | 5292 } else { |
| 5291 UNREACHABLE(); | 5293 UNREACHABLE(); |
| 5292 } | 5294 } |
| 5293 } | 5295 } |
| 5294 | 5296 |
| 5295 | 5297 |
| 5296 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5298 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5297 // ----------- S t a t e ------------- | 5299 // ----------- S t a t e ------------- |
| 5298 // -- r0 : argc (only if argument_count_ == ANY) | 5300 // -- r0 : argc (only if argument_count_ == ANY) |
| 5299 // -- r1 : constructor | 5301 // -- r1 : constructor |
| 5300 // -- r2 : feedback vector (fixed array or undefined) | 5302 // -- r2 : feedback vector (fixed array or megamorphic symbol) |
| 5301 // -- r3 : slot index (if r2 is fixed array) | 5303 // -- r3 : slot index (if r2 is fixed array) |
| 5302 // -- sp[0] : return address | 5304 // -- sp[0] : return address |
| 5303 // -- sp[4] : last argument | 5305 // -- sp[4] : last argument |
| 5304 // ----------------------------------- | 5306 // ----------------------------------- |
| 5307 |
| 5308 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
| 5309 masm->isolate()->heap()->megamorphic_symbol()); |
| 5310 |
| 5305 if (FLAG_debug_code) { | 5311 if (FLAG_debug_code) { |
| 5306 // The array construct code is only set for the global and natives | 5312 // The array construct code is only set for the global and natives |
| 5307 // builtin Array functions which always have maps. | 5313 // builtin Array functions which always have maps. |
| 5308 | 5314 |
| 5309 // Initial map for the builtin Array function should be a map. | 5315 // Initial map for the builtin Array function should be a map. |
| 5310 __ ldr(r4, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 5316 __ ldr(r4, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 5311 // Will both indicate a NULL and a Smi. | 5317 // Will both indicate a NULL and a Smi. |
| 5312 __ tst(r4, Operand(kSmiTagMask)); | 5318 __ tst(r4, Operand(kSmiTagMask)); |
| 5313 __ Assert(ne, kUnexpectedInitialMapForArrayFunction); | 5319 __ Assert(ne, kUnexpectedInitialMapForArrayFunction); |
| 5314 __ CompareObjectType(r4, r4, r5, MAP_TYPE); | 5320 __ CompareObjectType(r4, r4, r5, MAP_TYPE); |
| 5315 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); | 5321 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); |
| 5316 | 5322 |
| 5317 // We should either have undefined in ebx or a valid fixed array. | 5323 // We should either have the megamorphic symbol in ebx or a valid |
| 5324 // fixed array. |
| 5318 Label okay_here; | 5325 Label okay_here; |
| 5319 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); | 5326 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); |
| 5320 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); | 5327 __ CompareRoot(r2, Heap::kMegamorphicSymbolRootIndex); |
| 5321 __ b(eq, &okay_here); | 5328 __ b(eq, &okay_here); |
| 5322 __ ldr(r4, FieldMemOperand(r2, 0)); | 5329 __ ldr(r4, FieldMemOperand(r2, 0)); |
| 5323 __ cmp(r4, Operand(fixed_array_map)); | 5330 __ cmp(r4, Operand(fixed_array_map)); |
| 5324 __ Assert(eq, kExpectedFixedArrayInRegisterR2); | 5331 __ Assert(eq, kExpectedFixedArrayInRegisterR2); |
| 5325 | 5332 |
| 5326 // r3 should be a smi if we don't have undefined in r2 | 5333 // r3 should be a smi if we don't have undefined in r2 |
| 5327 __ AssertSmi(r3); | 5334 __ AssertSmi(r3); |
| 5328 | 5335 |
| 5329 __ bind(&okay_here); | 5336 __ bind(&okay_here); |
| 5330 } | 5337 } |
| 5331 | 5338 |
| 5332 Label no_info; | 5339 Label no_info; |
| 5333 // Get the elements kind and case on that. | 5340 // Get the elements kind and case on that. |
| 5334 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); | 5341 __ CompareRoot(r2, Heap::kMegamorphicSymbolRootIndex); |
| 5335 __ b(eq, &no_info); | 5342 __ b(eq, &no_info); |
| 5336 __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); | 5343 __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 5337 __ ldr(r2, FieldMemOperand(r2, FixedArray::kHeaderSize)); | 5344 __ ldr(r2, FieldMemOperand(r2, FixedArray::kHeaderSize)); |
| 5338 | 5345 |
| 5339 // If the feedback vector is undefined, or contains anything other than an | 5346 // If the feedback vector is undefined, or contains anything other than an |
| 5340 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 5347 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
| 5341 __ ldr(r4, FieldMemOperand(r2, 0)); | 5348 __ ldr(r4, FieldMemOperand(r2, 0)); |
| 5342 __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex); | 5349 __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex); |
| 5343 __ b(ne, &no_info); | 5350 __ b(ne, &no_info); |
| 5344 | 5351 |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5580 MemOperand(fp, 6 * kPointerSize), | 5587 MemOperand(fp, 6 * kPointerSize), |
| 5581 NULL); | 5588 NULL); |
| 5582 } | 5589 } |
| 5583 | 5590 |
| 5584 | 5591 |
| 5585 #undef __ | 5592 #undef __ |
| 5586 | 5593 |
| 5587 } } // namespace v8::internal | 5594 } } // namespace v8::internal |
| 5588 | 5595 |
| 5589 #endif // V8_TARGET_ARCH_ARM | 5596 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |