OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "code-stubs.h" | 9 #include "code-stubs.h" |
10 #include "codegen.h" | 10 #include "codegen.h" |
(...skipping 2301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2312 void FullCodeGenerator::CallIC(Handle<Code> code, | 2312 void FullCodeGenerator::CallIC(Handle<Code> code, |
2313 TypeFeedbackId ast_id) { | 2313 TypeFeedbackId ast_id) { |
2314 ic_total_count_++; | 2314 ic_total_count_++; |
2315 // All calls must have a predictable size in full-codegen code to ensure that | 2315 // All calls must have a predictable size in full-codegen code to ensure that |
2316 // the debugger can patch them correctly. | 2316 // the debugger can patch them correctly. |
2317 __ Call(code, RelocInfo::CODE_TARGET, ast_id); | 2317 __ Call(code, RelocInfo::CODE_TARGET, ast_id); |
2318 } | 2318 } |
2319 | 2319 |
2320 | 2320 |
2321 // Code common for calls using the IC. | 2321 // Code common for calls using the IC. |
2322 void FullCodeGenerator::EmitCallWithIC(Call* expr) { | 2322 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { |
2323 ASM_LOCATION("EmitCallWithIC"); | 2323 Expression* callee = expr->expression(); |
2324 | 2324 |
2325 Expression* callee = expr->expression(); | 2325 CallIC::CallType call_type = callee->IsVariableProxy() |
2326 ZoneList<Expression*>* args = expr->arguments(); | 2326 ? CallIC::FUNCTION |
2327 int arg_count = args->length(); | 2327 : CallIC::METHOD; |
2328 | 2328 |
2329 CallFunctionFlags flags; | |
2330 // Get the target function. | 2329 // Get the target function. |
2331 if (callee->IsVariableProxy()) { | 2330 if (call_type == CallIC::FUNCTION) { |
2332 { StackValueContext context(this); | 2331 { StackValueContext context(this); |
2333 EmitVariableLoad(callee->AsVariableProxy()); | 2332 EmitVariableLoad(callee->AsVariableProxy()); |
2334 PrepareForBailout(callee, NO_REGISTERS); | 2333 PrepareForBailout(callee, NO_REGISTERS); |
2335 } | 2334 } |
2336 // Push undefined as receiver. This is patched in the method prologue if it | 2335 // Push undefined as receiver. This is patched in the method prologue if it |
2337 // is a sloppy mode method. | 2336 // is a sloppy mode method. |
2338 __ Push(isolate()->factory()->undefined_value()); | 2337 __ Push(isolate()->factory()->undefined_value()); |
2339 flags = NO_CALL_FUNCTION_FLAGS; | |
2340 } else { | 2338 } else { |
2341 // Load the function from the receiver. | 2339 // Load the function from the receiver. |
2342 ASSERT(callee->IsProperty()); | 2340 ASSERT(callee->IsProperty()); |
2343 __ Peek(x0, 0); | 2341 __ Peek(x0, 0); |
2344 EmitNamedPropertyLoad(callee->AsProperty()); | 2342 EmitNamedPropertyLoad(callee->AsProperty()); |
2345 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2343 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2346 // Push the target function under the receiver. | 2344 // Push the target function under the receiver. |
2347 __ Pop(x10); | 2345 __ Pop(x10); |
2348 __ Push(x0, x10); | 2346 __ Push(x0, x10); |
2349 flags = CALL_AS_METHOD; | |
2350 } | 2347 } |
2351 | 2348 |
2352 // Load the arguments. | 2349 EmitCall(expr, call_type); |
2353 { PreservePositionScope scope(masm()->positions_recorder()); | |
2354 for (int i = 0; i < arg_count; i++) { | |
2355 VisitForStackValue(args->at(i)); | |
2356 } | |
2357 } | |
2358 | |
2359 // Record source position for debugger. | |
2360 SetSourcePosition(expr->position()); | |
2361 CallFunctionStub stub(isolate(), arg_count, flags); | |
2362 __ Peek(x1, (arg_count + 1) * kPointerSize); | |
2363 __ CallStub(&stub); | |
2364 | |
2365 RecordJSReturnSite(expr); | |
2366 | |
2367 // Restore context register. | |
2368 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2369 | |
2370 context()->DropAndPlug(1, x0); | |
2371 } | 2350 } |
2372 | 2351 |
2373 | 2352 |
2374 // Code common for calls using the IC. | 2353 // Code common for calls using the IC. |
2375 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2354 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2376 Expression* key) { | 2355 Expression* key) { |
2377 // Load the key. | 2356 // Load the key. |
2378 VisitForAccumulatorValue(key); | 2357 VisitForAccumulatorValue(key); |
2379 | 2358 |
2380 Expression* callee = expr->expression(); | 2359 Expression* callee = expr->expression(); |
2381 ZoneList<Expression*>* args = expr->arguments(); | |
2382 int arg_count = args->length(); | |
2383 | 2360 |
2384 // Load the function from the receiver. | 2361 // Load the function from the receiver. |
2385 ASSERT(callee->IsProperty()); | 2362 ASSERT(callee->IsProperty()); |
2386 __ Peek(x1, 0); | 2363 __ Peek(x1, 0); |
2387 EmitKeyedPropertyLoad(callee->AsProperty()); | 2364 EmitKeyedPropertyLoad(callee->AsProperty()); |
2388 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2365 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2389 | 2366 |
2390 // Push the target function under the receiver. | 2367 // Push the target function under the receiver. |
2391 __ Pop(x10); | 2368 __ Pop(x10); |
2392 __ Push(x0, x10); | 2369 __ Push(x0, x10); |
2393 | 2370 |
2394 { PreservePositionScope scope(masm()->positions_recorder()); | 2371 EmitCall(expr, CallIC::METHOD); |
2395 for (int i = 0; i < arg_count; i++) { | |
2396 VisitForStackValue(args->at(i)); | |
2397 } | |
2398 } | |
2399 | |
2400 // Record source position for debugger. | |
2401 SetSourcePosition(expr->position()); | |
2402 CallFunctionStub stub(isolate(), arg_count, CALL_AS_METHOD); | |
2403 __ Peek(x1, (arg_count + 1) * kPointerSize); | |
2404 __ CallStub(&stub); | |
2405 | |
2406 RecordJSReturnSite(expr); | |
2407 // Restore context register. | |
2408 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
2409 | |
2410 context()->DropAndPlug(1, x0); | |
2411 } | 2372 } |
2412 | 2373 |
2413 | 2374 |
2414 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2375 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) { |
2415 // Code common for calls using the call stub. | 2376 // Load the arguments. |
2416 ZoneList<Expression*>* args = expr->arguments(); | 2377 ZoneList<Expression*>* args = expr->arguments(); |
2417 int arg_count = args->length(); | 2378 int arg_count = args->length(); |
2418 { PreservePositionScope scope(masm()->positions_recorder()); | 2379 { PreservePositionScope scope(masm()->positions_recorder()); |
2419 for (int i = 0; i < arg_count; i++) { | 2380 for (int i = 0; i < arg_count; i++) { |
2420 VisitForStackValue(args->at(i)); | 2381 VisitForStackValue(args->at(i)); |
2421 } | 2382 } |
2422 } | 2383 } |
2423 // Record source position for debugger. | 2384 // Record source position of the IC call. |
2424 SetSourcePosition(expr->position()); | 2385 SetSourcePosition(expr->position()); |
2425 | 2386 |
2426 __ LoadObject(x2, FeedbackVector()); | 2387 Handle<Code> ic = CallIC::initialize_stub( |
| 2388 isolate(), arg_count, call_type); |
2427 __ Mov(x3, Smi::FromInt(expr->CallFeedbackSlot())); | 2389 __ Mov(x3, Smi::FromInt(expr->CallFeedbackSlot())); |
| 2390 __ Peek(x1, (arg_count + 1) * kXRegSize); |
| 2391 // Don't assign a type feedback id to the IC, since type feedback is provided |
| 2392 // by the vector above. |
| 2393 CallIC(ic); |
2428 | 2394 |
2429 // Record call targets in unoptimized code. | |
2430 CallFunctionStub stub(isolate(), arg_count, RECORD_CALL_TARGET); | |
2431 __ Peek(x1, (arg_count + 1) * kXRegSize); | |
2432 __ CallStub(&stub); | |
2433 RecordJSReturnSite(expr); | 2395 RecordJSReturnSite(expr); |
2434 // Restore context register. | 2396 // Restore context register. |
2435 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2397 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2436 context()->DropAndPlug(1, x0); | 2398 context()->DropAndPlug(1, x0); |
2437 } | 2399 } |
2438 | 2400 |
2439 | 2401 |
2440 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2402 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
2441 ASM_LOCATION("FullCodeGenerator::EmitResolvePossiblyDirectEval"); | 2403 ASM_LOCATION("FullCodeGenerator::EmitResolvePossiblyDirectEval"); |
2442 // Prepare to push a copy of the first argument or undefined if it doesn't | 2404 // Prepare to push a copy of the first argument or undefined if it doesn't |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2514 // Call the evaluated function. | 2476 // Call the evaluated function. |
2515 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | 2477 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); |
2516 __ Peek(x1, (arg_count + 1) * kXRegSize); | 2478 __ Peek(x1, (arg_count + 1) * kXRegSize); |
2517 __ CallStub(&stub); | 2479 __ CallStub(&stub); |
2518 RecordJSReturnSite(expr); | 2480 RecordJSReturnSite(expr); |
2519 // Restore context register. | 2481 // Restore context register. |
2520 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2482 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2521 context()->DropAndPlug(1, x0); | 2483 context()->DropAndPlug(1, x0); |
2522 | 2484 |
2523 } else if (call_type == Call::GLOBAL_CALL) { | 2485 } else if (call_type == Call::GLOBAL_CALL) { |
2524 EmitCallWithIC(expr); | 2486 EmitCallWithLoadIC(expr); |
2525 | 2487 |
2526 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 2488 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
2527 // Call to a lookup slot (dynamically introduced variable). | 2489 // Call to a lookup slot (dynamically introduced variable). |
2528 VariableProxy* proxy = callee->AsVariableProxy(); | 2490 VariableProxy* proxy = callee->AsVariableProxy(); |
2529 Label slow, done; | 2491 Label slow, done; |
2530 | 2492 |
2531 { PreservePositionScope scope(masm()->positions_recorder()); | 2493 { PreservePositionScope scope(masm()->positions_recorder()); |
2532 // Generate code for loading from variables potentially shadowed | 2494 // Generate code for loading from variables potentially shadowed |
2533 // by eval-introduced variables. | 2495 // by eval-introduced variables. |
2534 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2496 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
(...skipping 19 matching lines...) Expand all Loading... |
2554 __ Push(x0); | 2516 __ Push(x0); |
2555 // The receiver is implicitly the global receiver. Indicate this | 2517 // The receiver is implicitly the global receiver. Indicate this |
2556 // by passing the undefined to the call function stub. | 2518 // by passing the undefined to the call function stub. |
2557 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); | 2519 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); |
2558 __ Push(x1); | 2520 __ Push(x1); |
2559 __ Bind(&call); | 2521 __ Bind(&call); |
2560 } | 2522 } |
2561 | 2523 |
2562 // The receiver is either the global receiver or an object found | 2524 // The receiver is either the global receiver or an object found |
2563 // by LoadContextSlot. | 2525 // by LoadContextSlot. |
2564 EmitCallWithStub(expr); | 2526 EmitCall(expr); |
2565 } else if (call_type == Call::PROPERTY_CALL) { | 2527 } else if (call_type == Call::PROPERTY_CALL) { |
2566 Property* property = callee->AsProperty(); | 2528 Property* property = callee->AsProperty(); |
2567 { PreservePositionScope scope(masm()->positions_recorder()); | 2529 { PreservePositionScope scope(masm()->positions_recorder()); |
2568 VisitForStackValue(property->obj()); | 2530 VisitForStackValue(property->obj()); |
2569 } | 2531 } |
2570 if (property->key()->IsPropertyName()) { | 2532 if (property->key()->IsPropertyName()) { |
2571 EmitCallWithIC(expr); | 2533 EmitCallWithLoadIC(expr); |
2572 } else { | 2534 } else { |
2573 EmitKeyedCallWithIC(expr, property->key()); | 2535 EmitKeyedCallWithLoadIC(expr, property->key()); |
2574 } | 2536 } |
2575 | 2537 |
2576 } else { | 2538 } else { |
2577 ASSERT(call_type == Call::OTHER_CALL); | 2539 ASSERT(call_type == Call::OTHER_CALL); |
2578 // Call to an arbitrary expression not handled specially above. | 2540 // Call to an arbitrary expression not handled specially above. |
2579 { PreservePositionScope scope(masm()->positions_recorder()); | 2541 { PreservePositionScope scope(masm()->positions_recorder()); |
2580 VisitForStackValue(callee); | 2542 VisitForStackValue(callee); |
2581 } | 2543 } |
2582 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); | 2544 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); |
2583 __ Push(x1); | 2545 __ Push(x1); |
2584 // Emit function call. | 2546 // Emit function call. |
2585 EmitCallWithStub(expr); | 2547 EmitCall(expr); |
2586 } | 2548 } |
2587 | 2549 |
2588 #ifdef DEBUG | 2550 #ifdef DEBUG |
2589 // RecordJSReturnSite should have been called. | 2551 // RecordJSReturnSite should have been called. |
2590 ASSERT(expr->return_is_recorded_); | 2552 ASSERT(expr->return_is_recorded_); |
2591 #endif | 2553 #endif |
2592 } | 2554 } |
2593 | 2555 |
2594 | 2556 |
2595 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2557 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
(...skipping 25 matching lines...) Expand all Loading... |
2621 // Record call targets in unoptimized code. | 2583 // Record call targets in unoptimized code. |
2622 if (FLAG_pretenuring_call_new) { | 2584 if (FLAG_pretenuring_call_new) { |
2623 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); | 2585 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
2624 ASSERT(expr->AllocationSiteFeedbackSlot() == | 2586 ASSERT(expr->AllocationSiteFeedbackSlot() == |
2625 expr->CallNewFeedbackSlot() + 1); | 2587 expr->CallNewFeedbackSlot() + 1); |
2626 } | 2588 } |
2627 | 2589 |
2628 __ LoadObject(x2, FeedbackVector()); | 2590 __ LoadObject(x2, FeedbackVector()); |
2629 __ Mov(x3, Smi::FromInt(expr->CallNewFeedbackSlot())); | 2591 __ Mov(x3, Smi::FromInt(expr->CallNewFeedbackSlot())); |
2630 | 2592 |
2631 CallConstructStub stub(isolate(), RECORD_CALL_TARGET); | 2593 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
2632 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 2594 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
2633 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2595 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2634 context()->Plug(x0); | 2596 context()->Plug(x0); |
2635 } | 2597 } |
2636 | 2598 |
2637 | 2599 |
2638 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2600 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2639 ZoneList<Expression*>* args = expr->arguments(); | 2601 ZoneList<Expression*>* args = expr->arguments(); |
2640 ASSERT(args->length() == 1); | 2602 ASSERT(args->length() == 1); |
2641 | 2603 |
(...skipping 2327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4969 return previous_; | 4931 return previous_; |
4970 } | 4932 } |
4971 | 4933 |
4972 | 4934 |
4973 #undef __ | 4935 #undef __ |
4974 | 4936 |
4975 | 4937 |
4976 } } // namespace v8::internal | 4938 } } // namespace v8::internal |
4977 | 4939 |
4978 #endif // V8_TARGET_ARCH_ARM64 | 4940 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |