OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 2368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2379 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); | 2379 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
2380 __ SmiUntag(r9); | 2380 __ SmiUntag(r9); |
2381 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 2381 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
2382 __ jmp(&check_underlying); // Go to (4). | 2382 __ jmp(&check_underlying); // Go to (4). |
2383 #endif // V8_INTERPRETED_REGEXP | 2383 #endif // V8_INTERPRETED_REGEXP |
2384 } | 2384 } |
2385 | 2385 |
2386 | 2386 |
2387 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 2387 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
2388 // r0 : number of arguments to the construct function | 2388 // r0 : number of arguments to the construct function |
2389 // r2 : Feedback vector | 2389 // r1 : the function to call |
2390 // r2 : feedback vector | |
2390 // r3 : slot in feedback vector (Smi) | 2391 // r3 : slot in feedback vector (Smi) |
2391 // r1 : the function to call | 2392 // r4 : original constructor |
2392 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 2393 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
2393 | 2394 |
2394 // Number-of-arguments register must be smi-tagged to call out. | 2395 // Number-of-arguments register must be smi-tagged to call out. |
2395 __ SmiTag(r0); | 2396 __ SmiTag(r0); |
2396 __ Push(r3, r2, r1, r0); | 2397 __ Push(r3, r2, r1, r0); |
2398 __ Push(r4); | |
Michael Starzinger
2015/07/21 13:22:26
Please don't make me implement the Push() variant
jbramley
2015/07/21 13:28:02
It doesn't matter quite as much for ARM anyway, si
| |
2397 | 2399 |
2398 __ CallStub(stub); | 2400 __ CallStub(stub); |
2399 | 2401 |
2402 __ Pop(r4); | |
2400 __ Pop(r3, r2, r1, r0); | 2403 __ Pop(r3, r2, r1, r0); |
2401 __ SmiUntag(r0); | 2404 __ SmiUntag(r0); |
2402 } | 2405 } |
2403 | 2406 |
2404 | 2407 |
2405 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 2408 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
2406 // Cache the called function in a feedback vector slot. Cache states | 2409 // Cache the called function in a feedback vector slot. Cache states |
2407 // are uninitialized, monomorphic (indicated by a JSFunction), and | 2410 // are uninitialized, monomorphic (indicated by a JSFunction), and |
2408 // megamorphic. | 2411 // megamorphic. |
2409 // r0 : number of arguments to the construct function | 2412 // r0 : number of arguments to the construct function |
2410 // r1 : the function to call | 2413 // r1 : the function to call |
2411 // r2 : Feedback vector | 2414 // r2 : feedback vector |
2412 // r3 : slot in feedback vector (Smi) | 2415 // r3 : slot in feedback vector (Smi) |
2416 // r4 : original constructor | |
2413 Label initialize, done, miss, megamorphic, not_array_function; | 2417 Label initialize, done, miss, megamorphic, not_array_function; |
2414 | 2418 |
2415 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), | 2419 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), |
2416 masm->isolate()->heap()->megamorphic_symbol()); | 2420 masm->isolate()->heap()->megamorphic_symbol()); |
2417 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), | 2421 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), |
2418 masm->isolate()->heap()->uninitialized_symbol()); | 2422 masm->isolate()->heap()->uninitialized_symbol()); |
2419 | 2423 |
2420 // Load the cache state into r4. | 2424 // Load the cache state into r5. |
2421 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 2425 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); |
2422 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); | 2426 __ ldr(r5, FieldMemOperand(r5, FixedArray::kHeaderSize)); |
2423 | 2427 |
2424 // A monomorphic cache hit or an already megamorphic state: invoke the | 2428 // A monomorphic cache hit or an already megamorphic state: invoke the |
2425 // function without changing the state. | 2429 // function without changing the state. |
2426 // We don't know if r4 is a WeakCell or a Symbol, but it's harmless to read at | 2430 // We don't know if r5 is a WeakCell or a Symbol, but it's harmless to read at |
2427 // this position in a symbol (see static asserts in type-feedback-vector.h). | 2431 // this position in a symbol (see static asserts in type-feedback-vector.h). |
2428 Label check_allocation_site; | 2432 Label check_allocation_site; |
2429 Register feedback_map = r5; | 2433 Register feedback_map = r6; |
2430 Register weak_value = r6; | 2434 Register weak_value = r9; |
2431 __ ldr(weak_value, FieldMemOperand(r4, WeakCell::kValueOffset)); | 2435 __ ldr(weak_value, FieldMemOperand(r5, WeakCell::kValueOffset)); |
2432 __ cmp(r1, weak_value); | 2436 __ cmp(r1, weak_value); |
2433 __ b(eq, &done); | 2437 __ b(eq, &done); |
2434 __ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex); | 2438 __ CompareRoot(r5, Heap::kmegamorphic_symbolRootIndex); |
2435 __ b(eq, &done); | 2439 __ b(eq, &done); |
2436 __ ldr(feedback_map, FieldMemOperand(r4, HeapObject::kMapOffset)); | 2440 __ ldr(feedback_map, FieldMemOperand(r5, HeapObject::kMapOffset)); |
2437 __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); | 2441 __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); |
2438 __ b(ne, FLAG_pretenuring_call_new ? &miss : &check_allocation_site); | 2442 __ b(ne, FLAG_pretenuring_call_new ? &miss : &check_allocation_site); |
2439 | 2443 |
2440 // If the weak cell is cleared, we have a new chance to become monomorphic. | 2444 // If the weak cell is cleared, we have a new chance to become monomorphic. |
2441 __ JumpIfSmi(weak_value, &initialize); | 2445 __ JumpIfSmi(weak_value, &initialize); |
2442 __ jmp(&megamorphic); | 2446 __ jmp(&megamorphic); |
2443 | 2447 |
2444 if (!FLAG_pretenuring_call_new) { | 2448 if (!FLAG_pretenuring_call_new) { |
2445 __ bind(&check_allocation_site); | 2449 __ bind(&check_allocation_site); |
2446 // If we came here, we need to see if we are the array function. | 2450 // If we came here, we need to see if we are the array function. |
2447 // If we didn't have a matching function, and we didn't find the megamorph | 2451 // If we didn't have a matching function, and we didn't find the megamorph |
2448 // sentinel, then we have in the slot either some other function or an | 2452 // sentinel, then we have in the slot either some other function or an |
2449 // AllocationSite. | 2453 // AllocationSite. |
2450 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); | 2454 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); |
2451 __ b(ne, &miss); | 2455 __ b(ne, &miss); |
2452 | 2456 |
2453 // Make sure the function is the Array() function | 2457 // Make sure the function is the Array() function |
2454 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); | 2458 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r5); |
2455 __ cmp(r1, r4); | 2459 __ cmp(r1, r5); |
2456 __ b(ne, &megamorphic); | 2460 __ b(ne, &megamorphic); |
2457 __ jmp(&done); | 2461 __ jmp(&done); |
2458 } | 2462 } |
2459 | 2463 |
2460 __ bind(&miss); | 2464 __ bind(&miss); |
2461 | 2465 |
2462 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2466 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
2463 // megamorphic. | 2467 // megamorphic. |
2464 __ CompareRoot(r4, Heap::kuninitialized_symbolRootIndex); | 2468 __ CompareRoot(r5, Heap::kuninitialized_symbolRootIndex); |
2465 __ b(eq, &initialize); | 2469 __ b(eq, &initialize); |
2466 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2470 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
2467 // write-barrier is needed. | 2471 // write-barrier is needed. |
2468 __ bind(&megamorphic); | 2472 __ bind(&megamorphic); |
2469 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 2473 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); |
2470 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); | 2474 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); |
2471 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); | 2475 __ str(ip, FieldMemOperand(r5, FixedArray::kHeaderSize)); |
2472 __ jmp(&done); | 2476 __ jmp(&done); |
2473 | 2477 |
2474 // An uninitialized cache is patched with the function | 2478 // An uninitialized cache is patched with the function |
2475 __ bind(&initialize); | 2479 __ bind(&initialize); |
2476 | 2480 |
2477 if (!FLAG_pretenuring_call_new) { | 2481 if (!FLAG_pretenuring_call_new) { |
2478 // Make sure the function is the Array() function | 2482 // Make sure the function is the Array() function |
2479 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); | 2483 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r5); |
2480 __ cmp(r1, r4); | 2484 __ cmp(r1, r5); |
2481 __ b(ne, ¬_array_function); | 2485 __ b(ne, ¬_array_function); |
2482 | 2486 |
2483 // The target function is the Array constructor, | 2487 // The target function is the Array constructor, |
2484 // Create an AllocationSite if we don't already have it, store it in the | 2488 // Create an AllocationSite if we don't already have it, store it in the |
2485 // slot. | 2489 // slot. |
2486 CreateAllocationSiteStub create_stub(masm->isolate()); | 2490 CreateAllocationSiteStub create_stub(masm->isolate()); |
2487 CallStubInRecordCallTarget(masm, &create_stub); | 2491 CallStubInRecordCallTarget(masm, &create_stub); |
2488 __ b(&done); | 2492 __ b(&done); |
2489 | 2493 |
2490 __ bind(¬_array_function); | 2494 __ bind(¬_array_function); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2617 // r4 : original constructor (for IsSuperConstructorCall) | 2621 // r4 : original constructor (for IsSuperConstructorCall) |
2618 Label slow, non_function_call; | 2622 Label slow, non_function_call; |
2619 | 2623 |
2620 // Check that the function is not a smi. | 2624 // Check that the function is not a smi. |
2621 __ JumpIfSmi(r1, &non_function_call); | 2625 __ JumpIfSmi(r1, &non_function_call); |
2622 // Check that the function is a JSFunction. | 2626 // Check that the function is a JSFunction. |
2623 __ CompareObjectType(r1, r5, r5, JS_FUNCTION_TYPE); | 2627 __ CompareObjectType(r1, r5, r5, JS_FUNCTION_TYPE); |
2624 __ b(ne, &slow); | 2628 __ b(ne, &slow); |
2625 | 2629 |
2626 if (RecordCallTarget()) { | 2630 if (RecordCallTarget()) { |
2627 if (IsSuperConstructorCall()) { | |
2628 __ push(r4); | |
2629 } | |
2630 // TODO(mstarzinger): Consider tweaking target recording to avoid push/pop. | |
2631 GenerateRecordCallTarget(masm); | 2631 GenerateRecordCallTarget(masm); |
2632 if (IsSuperConstructorCall()) { | |
2633 __ pop(r4); | |
2634 } | |
2635 | 2632 |
2636 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); | 2633 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); |
2637 if (FLAG_pretenuring_call_new) { | 2634 if (FLAG_pretenuring_call_new) { |
2638 // Put the AllocationSite from the feedback vector into r2. | 2635 // Put the AllocationSite from the feedback vector into r2. |
2639 // By adding kPointerSize we encode that we know the AllocationSite | 2636 // By adding kPointerSize we encode that we know the AllocationSite |
2640 // entry is at the feedback vector slot given by r3 + 1. | 2637 // entry is at the feedback vector slot given by r3 + 1. |
2641 __ ldr(r2, FieldMemOperand(r5, FixedArray::kHeaderSize + kPointerSize)); | 2638 __ ldr(r2, FieldMemOperand(r5, FixedArray::kHeaderSize + kPointerSize)); |
2642 } else { | 2639 } else { |
2643 Label feedback_register_initialized; | 2640 Label feedback_register_initialized; |
2644 // Put the AllocationSite from the feedback vector into r2, or undefined. | 2641 // Put the AllocationSite from the feedback vector into r2, or undefined. |
(...skipping 2731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5376 MemOperand(fp, 6 * kPointerSize), NULL); | 5373 MemOperand(fp, 6 * kPointerSize), NULL); |
5377 } | 5374 } |
5378 | 5375 |
5379 | 5376 |
5380 #undef __ | 5377 #undef __ |
5381 | 5378 |
5382 } // namespace internal | 5379 } // namespace internal |
5383 } // namespace v8 | 5380 } // namespace v8 |
5384 | 5381 |
5385 #endif // V8_TARGET_ARCH_ARM | 5382 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |