| 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 2375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2386 // adaptor. | 2386 // adaptor. |
| 2387 if (!definitely_matches) { | 2387 if (!definitely_matches) { |
| 2388 Handle<Code> adaptor = | 2388 Handle<Code> adaptor = |
| 2389 isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 2389 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 2390 if (flag == CALL_FUNCTION) { | 2390 if (flag == CALL_FUNCTION) { |
| 2391 call_wrapper.BeforeCall(CallSize(adaptor)); | 2391 call_wrapper.BeforeCall(CallSize(adaptor)); |
| 2392 Call(adaptor); | 2392 Call(adaptor); |
| 2393 call_wrapper.AfterCall(); | 2393 call_wrapper.AfterCall(); |
| 2394 if (!*definitely_mismatches) { | 2394 if (!*definitely_mismatches) { |
| 2395 // If the arg counts don't match, no extra code is emitted by | 2395 // If the arg counts don't match, no extra code is emitted by |
| 2396 // MAsm::InvokeCode and we can just fall through. | 2396 // MAsm::InvokeFunctionCode and we can just fall through. |
| 2397 B(done); | 2397 B(done); |
| 2398 } | 2398 } |
| 2399 } else { | 2399 } else { |
| 2400 Jump(adaptor, RelocInfo::CODE_TARGET); | 2400 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 2401 } | 2401 } |
| 2402 } | 2402 } |
| 2403 Bind(®ular_invoke); | 2403 Bind(®ular_invoke); |
| 2404 } | 2404 } |
| 2405 | 2405 |
| 2406 | 2406 |
| 2407 void MacroAssembler::InvokeCode(Register code, | 2407 void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, |
| 2408 Register new_target, | 2408 const ParameterCount& expected, |
| 2409 const ParameterCount& expected, | 2409 const ParameterCount& actual) { |
| 2410 const ParameterCount& actual, | 2410 Label skip_flooding; |
| 2411 InvokeFlag flag, | 2411 ExternalReference debug_step_action = |
| 2412 const CallWrapper& call_wrapper) { | 2412 ExternalReference::debug_last_step_action_address(isolate()); |
| 2413 Mov(x4, Operand(debug_step_action)); |
| 2414 ldrb(x4, MemOperand(x4)); |
| 2415 CompareAndBranch(x4, Operand(StepIn), ne, &skip_flooding); |
| 2416 { |
| 2417 FrameScope frame(this, |
| 2418 has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); |
| 2419 if (expected.is_reg()) { |
| 2420 SmiTag(expected.reg()); |
| 2421 Push(expected.reg()); |
| 2422 } |
| 2423 if (actual.is_reg()) { |
| 2424 SmiTag(actual.reg()); |
| 2425 Push(actual.reg()); |
| 2426 } |
| 2427 if (new_target.is_valid()) { |
| 2428 Push(new_target); |
| 2429 } |
| 2430 Push(fun); |
| 2431 Push(fun); |
| 2432 CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1); |
| 2433 Pop(fun); |
| 2434 if (new_target.is_valid()) { |
| 2435 Pop(new_target); |
| 2436 } |
| 2437 if (actual.is_reg()) { |
| 2438 Pop(actual.reg()); |
| 2439 SmiUntag(actual.reg()); |
| 2440 } |
| 2441 if (expected.is_reg()) { |
| 2442 Pop(expected.reg()); |
| 2443 SmiUntag(expected.reg()); |
| 2444 } |
| 2445 } |
| 2446 bind(&skip_flooding); |
| 2447 } |
| 2448 |
| 2449 |
| 2450 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, |
| 2451 const ParameterCount& expected, |
| 2452 const ParameterCount& actual, |
| 2453 InvokeFlag flag, |
| 2454 const CallWrapper& call_wrapper) { |
| 2413 // You can't call a function without a valid frame. | 2455 // You can't call a function without a valid frame. |
| 2414 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2456 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2457 DCHECK(function.is(x1)); |
| 2458 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(x3)); |
| 2415 | 2459 |
| 2416 // Ensure new target is passed in the correct register. Otherwise clear the | 2460 FloodFunctionIfStepping(function, new_target, expected, actual); |
| 2417 // appropriate register in case new target is not given. | 2461 |
| 2418 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(x3)); | 2462 // Clear the new.target register if not given. |
| 2419 if (!new_target.is_valid()) { | 2463 if (!new_target.is_valid()) { |
| 2420 LoadRoot(x3, Heap::kUndefinedValueRootIndex); | 2464 LoadRoot(x3, Heap::kUndefinedValueRootIndex); |
| 2421 } | 2465 } |
| 2422 | 2466 |
| 2423 Label done; | 2467 Label done; |
| 2424 bool definitely_mismatches = false; | 2468 bool definitely_mismatches = false; |
| 2425 InvokePrologue(expected, actual, &done, flag, &definitely_mismatches, | 2469 InvokePrologue(expected, actual, &done, flag, &definitely_mismatches, |
| 2426 call_wrapper); | 2470 call_wrapper); |
| 2427 | 2471 |
| 2428 // If we are certain that actual != expected, then we know InvokePrologue will | 2472 // If we are certain that actual != expected, then we know InvokePrologue will |
| 2429 // have handled the call through the argument adaptor mechanism. | 2473 // have handled the call through the argument adaptor mechanism. |
| 2430 // The called function expects the call kind in x5. | 2474 // The called function expects the call kind in x5. |
| 2431 if (!definitely_mismatches) { | 2475 if (!definitely_mismatches) { |
| 2476 // We call indirectly through the code field in the function to |
| 2477 // allow recompilation to take effect without changing any of the |
| 2478 // call sites. |
| 2479 Register code = x4; |
| 2480 Ldr(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
| 2432 if (flag == CALL_FUNCTION) { | 2481 if (flag == CALL_FUNCTION) { |
| 2433 call_wrapper.BeforeCall(CallSize(code)); | 2482 call_wrapper.BeforeCall(CallSize(code)); |
| 2434 Call(code); | 2483 Call(code); |
| 2435 call_wrapper.AfterCall(); | 2484 call_wrapper.AfterCall(); |
| 2436 } else { | 2485 } else { |
| 2437 DCHECK(flag == JUMP_FUNCTION); | 2486 DCHECK(flag == JUMP_FUNCTION); |
| 2438 Jump(code); | 2487 Jump(code); |
| 2439 } | 2488 } |
| 2440 } | 2489 } |
| 2441 | 2490 |
| 2442 // Continue here if InvokePrologue does handle the invocation due to | 2491 // Continue here if InvokePrologue does handle the invocation due to |
| 2443 // mismatched parameter counts. | 2492 // mismatched parameter counts. |
| 2444 Bind(&done); | 2493 Bind(&done); |
| 2445 } | 2494 } |
| 2446 | 2495 |
| 2447 | 2496 |
| 2448 void MacroAssembler::InvokeFunction(Register function, | 2497 void MacroAssembler::InvokeFunction(Register function, |
| 2449 Register new_target, | 2498 Register new_target, |
| 2450 const ParameterCount& actual, | 2499 const ParameterCount& actual, |
| 2451 InvokeFlag flag, | 2500 InvokeFlag flag, |
| 2452 const CallWrapper& call_wrapper) { | 2501 const CallWrapper& call_wrapper) { |
| 2453 // You can't call a function without a valid frame. | 2502 // You can't call a function without a valid frame. |
| 2454 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2503 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2455 | 2504 |
| 2456 // Contract with called JS functions requires that function is passed in x1. | 2505 // Contract with called JS functions requires that function is passed in x1. |
| 2457 // (See FullCodeGenerator::Generate().) | 2506 // (See FullCodeGenerator::Generate().) |
| 2458 DCHECK(function.is(x1)); | 2507 DCHECK(function.is(x1)); |
| 2459 | 2508 |
| 2460 Register expected_reg = x2; | 2509 Register expected_reg = x2; |
| 2461 Register code_reg = x4; | |
| 2462 | 2510 |
| 2463 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | 2511 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 2464 // The number of arguments is stored as an int32_t, and -1 is a marker | 2512 // The number of arguments is stored as an int32_t, and -1 is a marker |
| 2465 // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign | 2513 // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign |
| 2466 // extension to correctly handle it. | 2514 // extension to correctly handle it. |
| 2467 Ldr(expected_reg, FieldMemOperand(function, | 2515 Ldr(expected_reg, FieldMemOperand(function, |
| 2468 JSFunction::kSharedFunctionInfoOffset)); | 2516 JSFunction::kSharedFunctionInfoOffset)); |
| 2469 Ldrsw(expected_reg, | 2517 Ldrsw(expected_reg, |
| 2470 FieldMemOperand(expected_reg, | 2518 FieldMemOperand(expected_reg, |
| 2471 SharedFunctionInfo::kFormalParameterCountOffset)); | 2519 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 2472 Ldr(code_reg, | |
| 2473 FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | |
| 2474 | 2520 |
| 2475 ParameterCount expected(expected_reg); | 2521 ParameterCount expected(expected_reg); |
| 2476 InvokeCode(code_reg, new_target, expected, actual, flag, call_wrapper); | 2522 InvokeFunctionCode(function, new_target, expected, actual, flag, |
| 2523 call_wrapper); |
| 2477 } | 2524 } |
| 2478 | 2525 |
| 2479 | 2526 |
| 2480 void MacroAssembler::InvokeFunction(Register function, | 2527 void MacroAssembler::InvokeFunction(Register function, |
| 2481 const ParameterCount& expected, | 2528 const ParameterCount& expected, |
| 2482 const ParameterCount& actual, | 2529 const ParameterCount& actual, |
| 2483 InvokeFlag flag, | 2530 InvokeFlag flag, |
| 2484 const CallWrapper& call_wrapper) { | 2531 const CallWrapper& call_wrapper) { |
| 2485 // You can't call a function without a valid frame. | 2532 // You can't call a function without a valid frame. |
| 2486 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2533 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2487 | 2534 |
| 2488 // Contract with called JS functions requires that function is passed in x1. | 2535 // Contract with called JS functions requires that function is passed in x1. |
| 2489 // (See FullCodeGenerator::Generate().) | 2536 // (See FullCodeGenerator::Generate().) |
| 2490 DCHECK(function.Is(x1)); | 2537 DCHECK(function.Is(x1)); |
| 2491 | 2538 |
| 2492 Register code_reg = x4; | |
| 2493 | |
| 2494 // Set up the context. | 2539 // Set up the context. |
| 2495 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | 2540 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 2496 | 2541 |
| 2497 // We call indirectly through the code field in the function to | 2542 InvokeFunctionCode(function, no_reg, expected, actual, flag, call_wrapper); |
| 2498 // allow recompilation to take effect without changing any of the | |
| 2499 // call sites. | |
| 2500 Ldr(code_reg, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | |
| 2501 InvokeCode(code_reg, no_reg, expected, actual, flag, call_wrapper); | |
| 2502 } | 2543 } |
| 2503 | 2544 |
| 2504 | 2545 |
| 2505 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 2546 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
| 2506 const ParameterCount& expected, | 2547 const ParameterCount& expected, |
| 2507 const ParameterCount& actual, | 2548 const ParameterCount& actual, |
| 2508 InvokeFlag flag, | 2549 InvokeFlag flag, |
| 2509 const CallWrapper& call_wrapper) { | 2550 const CallWrapper& call_wrapper) { |
| 2510 // Contract with called JS functions requires that function is passed in x1. | 2551 // Contract with called JS functions requires that function is passed in x1. |
| 2511 // (See FullCodeGenerator::Generate().) | 2552 // (See FullCodeGenerator::Generate().) |
| (...skipping 2416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4928 } | 4969 } |
| 4929 | 4970 |
| 4930 | 4971 |
| 4931 #undef __ | 4972 #undef __ |
| 4932 | 4973 |
| 4933 | 4974 |
| 4934 } // namespace internal | 4975 } // namespace internal |
| 4935 } // namespace v8 | 4976 } // namespace v8 |
| 4936 | 4977 |
| 4937 #endif // V8_TARGET_ARCH_ARM64 | 4978 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |