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 |