OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 3239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3250 | 3250 |
3251 // (9) Sliced string. Replace subject with parent. | 3251 // (9) Sliced string. Replace subject with parent. |
3252 __ Ldr(sliced_string_offset, | 3252 __ Ldr(sliced_string_offset, |
3253 UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset)); | 3253 UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset)); |
3254 __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 3254 __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
3255 __ B(&check_underlying); // Go to (4). | 3255 __ B(&check_underlying); // Go to (4). |
3256 #endif | 3256 #endif |
3257 } | 3257 } |
3258 | 3258 |
3259 | 3259 |
3260 // TODO(jbramley): Don't use static registers here, but take them as arguments. | 3260 static void GenerateRecordCallTarget(MacroAssembler* masm, |
3261 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 3261 Register argc, |
| 3262 Register function, |
| 3263 Register feedback_vector, |
| 3264 Register index, |
| 3265 Register scratch1, |
| 3266 Register scratch2) { |
3262 ASM_LOCATION("GenerateRecordCallTarget"); | 3267 ASM_LOCATION("GenerateRecordCallTarget"); |
| 3268 ASSERT(!AreAliased(scratch1, scratch2, |
| 3269 argc, function, feedback_vector, index)); |
3263 // Cache the called function in a feedback vector slot. Cache states are | 3270 // Cache the called function in a feedback vector slot. Cache states are |
3264 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. | 3271 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. |
3265 // x0 : number of arguments to the construct function | 3272 // argc : number of arguments to the construct function |
3266 // x1 : the function to call | 3273 // function : the function to call |
3267 // x2 : feedback vector | 3274 // feedback_vector : the feedback vector |
3268 // x3 : slot in feedback vector (smi) | 3275 // index : slot in feedback vector (smi) |
3269 Label initialize, done, miss, megamorphic, not_array_function; | 3276 Label initialize, done, miss, megamorphic, not_array_function; |
3270 | 3277 |
3271 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3278 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
3272 masm->isolate()->heap()->undefined_value()); | 3279 masm->isolate()->heap()->undefined_value()); |
3273 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), | 3280 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), |
3274 masm->isolate()->heap()->the_hole_value()); | 3281 masm->isolate()->heap()->the_hole_value()); |
3275 | 3282 |
3276 // Load the cache state. | 3283 // Load the cache state. |
3277 __ Add(x4, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); | 3284 __ Add(scratch1, feedback_vector, |
3278 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 3285 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 3286 __ Ldr(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); |
3279 | 3287 |
3280 // A monomorphic cache hit or an already megamorphic state: invoke the | 3288 // A monomorphic cache hit or an already megamorphic state: invoke the |
3281 // function without changing the state. | 3289 // function without changing the state. |
3282 __ Cmp(x4, x1); | 3290 __ Cmp(scratch1, function); |
3283 __ B(eq, &done); | 3291 __ B(eq, &done); |
3284 | 3292 |
3285 // If we came here, we need to see if we are the array function. | 3293 // If we came here, we need to see if we are the array function. |
3286 // If we didn't have a matching function, and we didn't find the megamorph | 3294 // If we didn't have a matching function, and we didn't find the megamorph |
3287 // sentinel, then we have in the slot either some other function or an | 3295 // sentinel, then we have in the slot either some other function or an |
3288 // AllocationSite. Do a map check on the object in ecx. | 3296 // AllocationSite. Do a map check on the object in scratch1 register. |
3289 __ Ldr(x5, FieldMemOperand(x4, AllocationSite::kMapOffset)); | 3297 __ Ldr(scratch2, FieldMemOperand(scratch1, AllocationSite::kMapOffset)); |
3290 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, &miss); | 3298 __ JumpIfNotRoot(scratch2, Heap::kAllocationSiteMapRootIndex, &miss); |
3291 | 3299 |
3292 // Make sure the function is the Array() function | 3300 // Make sure the function is the Array() function |
3293 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, x4); | 3301 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch1); |
3294 __ Cmp(x1, x4); | 3302 __ Cmp(function, scratch1); |
3295 __ B(ne, &megamorphic); | 3303 __ B(ne, &megamorphic); |
3296 __ B(&done); | 3304 __ B(&done); |
3297 | 3305 |
3298 __ Bind(&miss); | 3306 __ Bind(&miss); |
3299 | 3307 |
3300 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3308 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
3301 // megamorphic. | 3309 // megamorphic. |
3302 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &initialize); | 3310 __ JumpIfRoot(scratch1, Heap::kTheHoleValueRootIndex, &initialize); |
3303 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3311 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
3304 // write-barrier is needed. | 3312 // write-barrier is needed. |
3305 __ Bind(&megamorphic); | 3313 __ Bind(&megamorphic); |
3306 __ Add(x4, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); | 3314 __ Add(scratch1, feedback_vector, |
3307 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 3315 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
3308 __ Str(x10, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 3316 __ LoadRoot(scratch2, Heap::kUndefinedValueRootIndex); |
| 3317 __ Str(scratch2, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); |
3309 __ B(&done); | 3318 __ B(&done); |
3310 | 3319 |
3311 // An uninitialized cache is patched with the function or sentinel to | 3320 // An uninitialized cache is patched with the function or sentinel to |
3312 // indicate the ElementsKind if function is the Array constructor. | 3321 // indicate the ElementsKind if function is the Array constructor. |
3313 __ Bind(&initialize); | 3322 __ Bind(&initialize); |
3314 // Make sure the function is the Array() function | 3323 // Make sure the function is the Array() function |
3315 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, x4); | 3324 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch1); |
3316 __ Cmp(x1, x4); | 3325 __ Cmp(function, scratch1); |
3317 __ B(ne, ¬_array_function); | 3326 __ B(ne, ¬_array_function); |
3318 | 3327 |
3319 // The target function is the Array constructor, | 3328 // The target function is the Array constructor, |
3320 // Create an AllocationSite if we don't already have it, store it in the slot. | 3329 // Create an AllocationSite if we don't already have it, store it in the slot. |
3321 { | 3330 { |
3322 FrameScope scope(masm, StackFrame::INTERNAL); | 3331 FrameScope scope(masm, StackFrame::INTERNAL); |
3323 CreateAllocationSiteStub create_stub; | 3332 CreateAllocationSiteStub create_stub; |
3324 | 3333 |
3325 // Arguments register must be smi-tagged to call out. | 3334 // Arguments register must be smi-tagged to call out. |
3326 __ SmiTag(x0); | 3335 __ SmiTag(argc); |
3327 __ Push(x0, x1, x2, x3); | 3336 __ Push(argc, function, feedback_vector, index); |
3328 | 3337 |
| 3338 // CreateAllocationSiteStub expect the feedback vector in x2 and the slot |
| 3339 // index in x3. |
| 3340 ASSERT(feedback_vector.Is(x2) && index.Is(x3)); |
3329 __ CallStub(&create_stub); | 3341 __ CallStub(&create_stub); |
3330 | 3342 |
3331 __ Pop(x3, x2, x1, x0); | 3343 __ Pop(index, feedback_vector, function, argc); |
3332 __ SmiUntag(x0); | 3344 __ SmiUntag(argc); |
3333 } | 3345 } |
3334 __ B(&done); | 3346 __ B(&done); |
3335 | 3347 |
3336 __ Bind(¬_array_function); | 3348 __ Bind(¬_array_function); |
3337 // An uninitialized cache is patched with the function. | 3349 // An uninitialized cache is patched with the function. |
3338 | 3350 |
3339 __ Add(x4, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); | 3351 __ Add(scratch1, feedback_vector, |
3340 // TODO(all): Does the value need to be left in x4? If not, FieldMemOperand | 3352 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
3341 // could be used to avoid this add. | 3353 __ Add(scratch1, scratch1, FixedArray::kHeaderSize - kHeapObjectTag); |
3342 __ Add(x4, x4, FixedArray::kHeaderSize - kHeapObjectTag); | 3354 __ Str(function, MemOperand(scratch1, 0)); |
3343 __ Str(x1, MemOperand(x4, 0)); | |
3344 | 3355 |
3345 __ Push(x4, x2, x1); | 3356 __ Push(function); |
3346 __ RecordWrite(x2, x4, x1, kLRHasNotBeenSaved, kDontSaveFPRegs, | 3357 __ RecordWrite(feedback_vector, scratch1, function, kLRHasNotBeenSaved, |
3347 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 3358 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
3348 __ Pop(x1, x2, x4); | 3359 __ Pop(function); |
3349 | |
3350 // TODO(all): Are x4, x2 and x1 outputs? This isn't clear. | |
3351 | 3360 |
3352 __ Bind(&done); | 3361 __ Bind(&done); |
3353 } | 3362 } |
3354 | 3363 |
3355 | 3364 |
3356 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3365 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3357 ASM_LOCATION("CallFunctionStub::Generate"); | 3366 ASM_LOCATION("CallFunctionStub::Generate"); |
3358 // x1 function the function to call | 3367 // x1 function the function to call |
3359 // x2 : feedback vector | 3368 // x2 : feedback vector |
3360 // x3 : slot in feedback vector (smi) (if x2 is not undefined) | 3369 // x3 : slot in feedback vector (smi) (if x2 is not undefined) |
3361 Register function = x1; | 3370 Register function = x1; |
3362 Register cache_cell = x2; | 3371 Register cache_cell = x2; |
3363 Register slot = x3; | 3372 Register slot = x3; |
3364 Register type = x4; | 3373 Register type = x4; |
3365 Label slow, non_function, wrap, cont; | 3374 Label slow, non_function, wrap, cont; |
3366 | 3375 |
3367 // TODO(jbramley): This function has a lot of unnamed registers. Name them, | 3376 // TODO(jbramley): This function has a lot of unnamed registers. Name them, |
3368 // and tidy things up a bit. | 3377 // and tidy things up a bit. |
3369 | 3378 |
3370 if (NeedsChecks()) { | 3379 if (NeedsChecks()) { |
3371 // Check that the function is really a JavaScript function. | 3380 // Check that the function is really a JavaScript function. |
3372 __ JumpIfSmi(function, &non_function); | 3381 __ JumpIfSmi(function, &non_function); |
3373 | 3382 |
3374 // Goto slow case if we do not have a function. | 3383 // Goto slow case if we do not have a function. |
3375 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); | 3384 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); |
3376 | 3385 |
3377 if (RecordCallTarget()) { | 3386 if (RecordCallTarget()) { |
3378 GenerateRecordCallTarget(masm); | 3387 GenerateRecordCallTarget(masm, x0, function, cache_cell, slot, x4, x5); |
3379 } | 3388 } |
3380 } | 3389 } |
3381 | 3390 |
3382 // Fast-case: Invoke the function now. | 3391 // Fast-case: Invoke the function now. |
3383 // x1 function pushed function | 3392 // x1 function pushed function |
3384 ParameterCount actual(argc_); | 3393 ParameterCount actual(argc_); |
3385 | 3394 |
3386 if (CallAsMethod()) { | 3395 if (CallAsMethod()) { |
3387 if (NeedsChecks()) { | 3396 if (NeedsChecks()) { |
3388 // Do not transform the receiver for strict mode functions. | 3397 // Do not transform the receiver for strict mode functions. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3473 Label slow, non_function_call; | 3482 Label slow, non_function_call; |
3474 | 3483 |
3475 // Check that the function is not a smi. | 3484 // Check that the function is not a smi. |
3476 __ JumpIfSmi(function, &non_function_call); | 3485 __ JumpIfSmi(function, &non_function_call); |
3477 // Check that the function is a JSFunction. | 3486 // Check that the function is a JSFunction. |
3478 Register object_type = x10; | 3487 Register object_type = x10; |
3479 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE, | 3488 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE, |
3480 &slow); | 3489 &slow); |
3481 | 3490 |
3482 if (RecordCallTarget()) { | 3491 if (RecordCallTarget()) { |
3483 GenerateRecordCallTarget(masm); | 3492 GenerateRecordCallTarget(masm, x0, function, x2, x3, x4, x5); |
3484 } | 3493 } |
3485 | 3494 |
3486 // Jump to the function-specific construct stub. | 3495 // Jump to the function-specific construct stub. |
3487 Register jump_reg = x4; | 3496 Register jump_reg = x4; |
3488 Register shared_func_info = jump_reg; | 3497 Register shared_func_info = jump_reg; |
3489 Register cons_stub = jump_reg; | 3498 Register cons_stub = jump_reg; |
3490 Register cons_stub_code = jump_reg; | 3499 Register cons_stub_code = jump_reg; |
3491 __ Ldr(shared_func_info, | 3500 __ Ldr(shared_func_info, |
3492 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3501 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
3493 __ Ldr(cons_stub, | 3502 __ Ldr(cons_stub, |
(...skipping 2302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5796 MemOperand(fp, 6 * kPointerSize), | 5805 MemOperand(fp, 6 * kPointerSize), |
5797 NULL); | 5806 NULL); |
5798 } | 5807 } |
5799 | 5808 |
5800 | 5809 |
5801 #undef __ | 5810 #undef __ |
5802 | 5811 |
5803 } } // namespace v8::internal | 5812 } } // namespace v8::internal |
5804 | 5813 |
5805 #endif // V8_TARGET_ARCH_A64 | 5814 #endif // V8_TARGET_ARCH_A64 |
OLD | NEW |