| 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 |