| 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 1495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1506 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 1506 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| 1507 InvokeFlag flag, | 1507 InvokeFlag flag, |
| 1508 const CallWrapper& call_wrapper) { | 1508 const CallWrapper& call_wrapper) { |
| 1509 ASM_LOCATION("MacroAssembler::InvokeBuiltin"); | 1509 ASM_LOCATION("MacroAssembler::InvokeBuiltin"); |
| 1510 // You can't call a builtin without a valid frame. | 1510 // You can't call a builtin without a valid frame. |
| 1511 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 1511 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
| 1512 | 1512 |
| 1513 GetBuiltinEntry(x2, id); | 1513 GetBuiltinEntry(x2, id); |
| 1514 if (flag == CALL_FUNCTION) { | 1514 if (flag == CALL_FUNCTION) { |
| 1515 call_wrapper.BeforeCall(CallSize(x2)); | 1515 call_wrapper.BeforeCall(CallSize(x2)); |
| 1516 SetCallKind(x5, CALL_AS_METHOD); | |
| 1517 Call(x2); | 1516 Call(x2); |
| 1518 call_wrapper.AfterCall(); | 1517 call_wrapper.AfterCall(); |
| 1519 } else { | 1518 } else { |
| 1520 ASSERT(flag == JUMP_FUNCTION); | 1519 ASSERT(flag == JUMP_FUNCTION); |
| 1521 SetCallKind(x5, CALL_AS_METHOD); | |
| 1522 Jump(x2); | 1520 Jump(x2); |
| 1523 } | 1521 } |
| 1524 } | 1522 } |
| 1525 | 1523 |
| 1526 | 1524 |
| 1527 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, | 1525 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, |
| 1528 int num_arguments, | 1526 int num_arguments, |
| 1529 int result_size) { | 1527 int result_size) { |
| 1530 // TODO(1236192): Most runtime routines don't need the number of | 1528 // TODO(1236192): Most runtime routines don't need the number of |
| 1531 // arguments passed in because it is constant. At some point we | 1529 // arguments passed in because it is constant. At some point we |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2291 } | 2289 } |
| 2292 | 2290 |
| 2293 | 2291 |
| 2294 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 2292 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
| 2295 const ParameterCount& actual, | 2293 const ParameterCount& actual, |
| 2296 Handle<Code> code_constant, | 2294 Handle<Code> code_constant, |
| 2297 Register code_reg, | 2295 Register code_reg, |
| 2298 Label* done, | 2296 Label* done, |
| 2299 InvokeFlag flag, | 2297 InvokeFlag flag, |
| 2300 bool* definitely_mismatches, | 2298 bool* definitely_mismatches, |
| 2301 const CallWrapper& call_wrapper, | 2299 const CallWrapper& call_wrapper) { |
| 2302 CallKind call_kind) { | |
| 2303 bool definitely_matches = false; | 2300 bool definitely_matches = false; |
| 2304 *definitely_mismatches = false; | 2301 *definitely_mismatches = false; |
| 2305 Label regular_invoke; | 2302 Label regular_invoke; |
| 2306 | 2303 |
| 2307 // Check whether the expected and actual arguments count match. If not, | 2304 // Check whether the expected and actual arguments count match. If not, |
| 2308 // setup registers according to contract with ArgumentsAdaptorTrampoline: | 2305 // setup registers according to contract with ArgumentsAdaptorTrampoline: |
| 2309 // x0: actual arguments count. | 2306 // x0: actual arguments count. |
| 2310 // x1: function (passed through to callee). | 2307 // x1: function (passed through to callee). |
| 2311 // x2: expected arguments count. | 2308 // x2: expected arguments count. |
| 2312 // x3: callee code entry. | |
| 2313 | 2309 |
| 2314 // The code below is made a lot easier because the calling code already sets | 2310 // The code below is made a lot easier because the calling code already sets |
| 2315 // up actual and expected registers according to the contract if values are | 2311 // up actual and expected registers according to the contract if values are |
| 2316 // passed in registers. | 2312 // passed in registers. |
| 2317 ASSERT(actual.is_immediate() || actual.reg().is(x0)); | 2313 ASSERT(actual.is_immediate() || actual.reg().is(x0)); |
| 2318 ASSERT(expected.is_immediate() || expected.reg().is(x2)); | 2314 ASSERT(expected.is_immediate() || expected.reg().is(x2)); |
| 2319 ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(x3)); | 2315 ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(x3)); |
| 2320 | 2316 |
| 2321 if (expected.is_immediate()) { | 2317 if (expected.is_immediate()) { |
| 2322 ASSERT(actual.is_immediate()); | 2318 ASSERT(actual.is_immediate()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 if (!definitely_matches) { | 2350 if (!definitely_matches) { |
| 2355 if (!code_constant.is_null()) { | 2351 if (!code_constant.is_null()) { |
| 2356 Mov(x3, Operand(code_constant)); | 2352 Mov(x3, Operand(code_constant)); |
| 2357 Add(x3, x3, Code::kHeaderSize - kHeapObjectTag); | 2353 Add(x3, x3, Code::kHeaderSize - kHeapObjectTag); |
| 2358 } | 2354 } |
| 2359 | 2355 |
| 2360 Handle<Code> adaptor = | 2356 Handle<Code> adaptor = |
| 2361 isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 2357 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 2362 if (flag == CALL_FUNCTION) { | 2358 if (flag == CALL_FUNCTION) { |
| 2363 call_wrapper.BeforeCall(CallSize(adaptor)); | 2359 call_wrapper.BeforeCall(CallSize(adaptor)); |
| 2364 SetCallKind(x5, call_kind); | |
| 2365 Call(adaptor); | 2360 Call(adaptor); |
| 2366 call_wrapper.AfterCall(); | 2361 call_wrapper.AfterCall(); |
| 2367 if (!*definitely_mismatches) { | 2362 if (!*definitely_mismatches) { |
| 2368 // If the arg counts don't match, no extra code is emitted by | 2363 // If the arg counts don't match, no extra code is emitted by |
| 2369 // MAsm::InvokeCode and we can just fall through. | 2364 // MAsm::InvokeCode and we can just fall through. |
| 2370 B(done); | 2365 B(done); |
| 2371 } | 2366 } |
| 2372 } else { | 2367 } else { |
| 2373 SetCallKind(x5, call_kind); | |
| 2374 Jump(adaptor, RelocInfo::CODE_TARGET); | 2368 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 2375 } | 2369 } |
| 2376 } | 2370 } |
| 2377 Bind(®ular_invoke); | 2371 Bind(®ular_invoke); |
| 2378 } | 2372 } |
| 2379 | 2373 |
| 2380 | 2374 |
| 2381 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { | |
| 2382 // This macro takes the dst register to make the code more readable | |
| 2383 // at the call sites. However, the dst register has to be x5 to | |
| 2384 // follow the calling convention which requires the call type to be | |
| 2385 // in x5. | |
| 2386 // | |
| 2387 // For example Builtins::Generate_LazyCompile requires this. | |
| 2388 ASSERT(dst.is(x5)); | |
| 2389 if (call_kind == CALL_AS_FUNCTION) { | |
| 2390 Mov(dst, Operand(Smi::FromInt(1))); | |
| 2391 } else { | |
| 2392 Mov(dst, Operand(Smi::FromInt(0))); | |
| 2393 } | |
| 2394 } | |
| 2395 | |
| 2396 | |
| 2397 void MacroAssembler::InvokeCode(Register code, | 2375 void MacroAssembler::InvokeCode(Register code, |
| 2398 const ParameterCount& expected, | 2376 const ParameterCount& expected, |
| 2399 const ParameterCount& actual, | 2377 const ParameterCount& actual, |
| 2400 InvokeFlag flag, | 2378 InvokeFlag flag, |
| 2401 const CallWrapper& call_wrapper, | 2379 const CallWrapper& call_wrapper) { |
| 2402 CallKind call_kind) { | |
| 2403 // You can't call a function without a valid frame. | 2380 // You can't call a function without a valid frame. |
| 2404 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 2381 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
| 2405 | 2382 |
| 2406 Label done; | 2383 Label done; |
| 2407 | 2384 |
| 2408 bool definitely_mismatches = false; | 2385 bool definitely_mismatches = false; |
| 2409 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, | 2386 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, |
| 2410 &definitely_mismatches, call_wrapper, call_kind); | 2387 &definitely_mismatches, call_wrapper); |
| 2411 | 2388 |
| 2412 // If we are certain that actual != expected, then we know InvokePrologue will | 2389 // If we are certain that actual != expected, then we know InvokePrologue will |
| 2413 // have handled the call through the argument adaptor mechanism. | 2390 // have handled the call through the argument adaptor mechanism. |
| 2414 // The called function expects the call kind in x5. | 2391 // The called function expects the call kind in x5. |
| 2415 if (!definitely_mismatches) { | 2392 if (!definitely_mismatches) { |
| 2416 if (flag == CALL_FUNCTION) { | 2393 if (flag == CALL_FUNCTION) { |
| 2417 call_wrapper.BeforeCall(CallSize(code)); | 2394 call_wrapper.BeforeCall(CallSize(code)); |
| 2418 SetCallKind(x5, call_kind); | |
| 2419 Call(code); | 2395 Call(code); |
| 2420 call_wrapper.AfterCall(); | 2396 call_wrapper.AfterCall(); |
| 2421 } else { | 2397 } else { |
| 2422 ASSERT(flag == JUMP_FUNCTION); | 2398 ASSERT(flag == JUMP_FUNCTION); |
| 2423 SetCallKind(x5, call_kind); | |
| 2424 Jump(code); | 2399 Jump(code); |
| 2425 } | 2400 } |
| 2426 } | 2401 } |
| 2427 | 2402 |
| 2428 // Continue here if InvokePrologue does handle the invocation due to | 2403 // Continue here if InvokePrologue does handle the invocation due to |
| 2429 // mismatched parameter counts. | 2404 // mismatched parameter counts. |
| 2430 Bind(&done); | 2405 Bind(&done); |
| 2431 } | 2406 } |
| 2432 | 2407 |
| 2433 | 2408 |
| 2434 void MacroAssembler::InvokeCode(Handle<Code> code, | |
| 2435 const ParameterCount& expected, | |
| 2436 const ParameterCount& actual, | |
| 2437 RelocInfo::Mode rmode, | |
| 2438 InvokeFlag flag, | |
| 2439 CallKind call_kind) { | |
| 2440 // You can't call a function without a valid frame. | |
| 2441 ASSERT(flag == JUMP_FUNCTION || has_frame()); | |
| 2442 | |
| 2443 Label done; | |
| 2444 bool definitely_mismatches = false; | |
| 2445 InvokePrologue(expected, actual, code, NoReg, &done, flag, | |
| 2446 &definitely_mismatches, NullCallWrapper(), call_kind); | |
| 2447 | |
| 2448 // The called function expects the call kind in x5. | |
| 2449 SetCallKind(x5, call_kind); | |
| 2450 if (flag == CALL_FUNCTION) { | |
| 2451 Call(code, rmode); | |
| 2452 } else { | |
| 2453 Jump(code, rmode); | |
| 2454 } | |
| 2455 | |
| 2456 // Continue here if InvokePrologue does handle the invocation due to | |
| 2457 // mismatched parameter counts. | |
| 2458 Bind(&done); | |
| 2459 } | |
| 2460 | |
| 2461 | |
| 2462 void MacroAssembler::InvokeFunction(Register function, | 2409 void MacroAssembler::InvokeFunction(Register function, |
| 2463 const ParameterCount& actual, | 2410 const ParameterCount& actual, |
| 2464 InvokeFlag flag, | 2411 InvokeFlag flag, |
| 2465 const CallWrapper& call_wrapper, | 2412 const CallWrapper& call_wrapper) { |
| 2466 CallKind call_kind) { | |
| 2467 // You can't call a function without a valid frame. | 2413 // You can't call a function without a valid frame. |
| 2468 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 2414 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
| 2469 | 2415 |
| 2470 // Contract with called JS functions requires that function is passed in x1. | 2416 // Contract with called JS functions requires that function is passed in x1. |
| 2471 // (See FullCodeGenerator::Generate().) | 2417 // (See FullCodeGenerator::Generate().) |
| 2472 ASSERT(function.is(x1)); | 2418 ASSERT(function.is(x1)); |
| 2473 | 2419 |
| 2474 Register expected_reg = x2; | 2420 Register expected_reg = x2; |
| 2475 Register code_reg = x3; | 2421 Register code_reg = x3; |
| 2476 | 2422 |
| 2477 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | 2423 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 2478 // The number of arguments is stored as an int32_t, and -1 is a marker | 2424 // The number of arguments is stored as an int32_t, and -1 is a marker |
| 2479 // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign | 2425 // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign |
| 2480 // extension to correctly handle it. | 2426 // extension to correctly handle it. |
| 2481 Ldr(expected_reg, FieldMemOperand(function, | 2427 Ldr(expected_reg, FieldMemOperand(function, |
| 2482 JSFunction::kSharedFunctionInfoOffset)); | 2428 JSFunction::kSharedFunctionInfoOffset)); |
| 2483 Ldrsw(expected_reg, | 2429 Ldrsw(expected_reg, |
| 2484 FieldMemOperand(expected_reg, | 2430 FieldMemOperand(expected_reg, |
| 2485 SharedFunctionInfo::kFormalParameterCountOffset)); | 2431 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 2486 Ldr(code_reg, | 2432 Ldr(code_reg, |
| 2487 FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | 2433 FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
| 2488 | 2434 |
| 2489 ParameterCount expected(expected_reg); | 2435 ParameterCount expected(expected_reg); |
| 2490 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); | 2436 InvokeCode(code_reg, expected, actual, flag, call_wrapper); |
| 2491 } | 2437 } |
| 2492 | 2438 |
| 2493 | 2439 |
| 2494 void MacroAssembler::InvokeFunction(Register function, | 2440 void MacroAssembler::InvokeFunction(Register function, |
| 2495 const ParameterCount& expected, | 2441 const ParameterCount& expected, |
| 2496 const ParameterCount& actual, | 2442 const ParameterCount& actual, |
| 2497 InvokeFlag flag, | 2443 InvokeFlag flag, |
| 2498 const CallWrapper& call_wrapper, | 2444 const CallWrapper& call_wrapper) { |
| 2499 CallKind call_kind) { | |
| 2500 // You can't call a function without a valid frame. | 2445 // You can't call a function without a valid frame. |
| 2501 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 2446 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
| 2502 | 2447 |
| 2503 // Contract with called JS functions requires that function is passed in x1. | 2448 // Contract with called JS functions requires that function is passed in x1. |
| 2504 // (See FullCodeGenerator::Generate().) | 2449 // (See FullCodeGenerator::Generate().) |
| 2505 ASSERT(function.Is(x1)); | 2450 ASSERT(function.Is(x1)); |
| 2506 | 2451 |
| 2507 Register code_reg = x3; | 2452 Register code_reg = x3; |
| 2508 | 2453 |
| 2509 // Set up the context. | 2454 // Set up the context. |
| 2510 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); | 2455 Ldr(cp, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 2511 | 2456 |
| 2512 // We call indirectly through the code field in the function to | 2457 // We call indirectly through the code field in the function to |
| 2513 // allow recompilation to take effect without changing any of the | 2458 // allow recompilation to take effect without changing any of the |
| 2514 // call sites. | 2459 // call sites. |
| 2515 Ldr(code_reg, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | 2460 Ldr(code_reg, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
| 2516 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); | 2461 InvokeCode(code_reg, expected, actual, flag, call_wrapper); |
| 2517 } | 2462 } |
| 2518 | 2463 |
| 2519 | 2464 |
| 2520 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 2465 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
| 2521 const ParameterCount& expected, | 2466 const ParameterCount& expected, |
| 2522 const ParameterCount& actual, | 2467 const ParameterCount& actual, |
| 2523 InvokeFlag flag, | 2468 InvokeFlag flag, |
| 2524 const CallWrapper& call_wrapper, | 2469 const CallWrapper& call_wrapper) { |
| 2525 CallKind call_kind) { | |
| 2526 // Contract with called JS functions requires that function is passed in x1. | 2470 // Contract with called JS functions requires that function is passed in x1. |
| 2527 // (See FullCodeGenerator::Generate().) | 2471 // (See FullCodeGenerator::Generate().) |
| 2528 __ LoadObject(x1, function); | 2472 __ LoadObject(x1, function); |
| 2529 InvokeFunction(x1, expected, actual, flag, call_wrapper, call_kind); | 2473 InvokeFunction(x1, expected, actual, flag, call_wrapper); |
| 2530 } | 2474 } |
| 2531 | 2475 |
| 2532 | 2476 |
| 2533 void MacroAssembler::ECMA262ToInt32(Register result, | 2477 void MacroAssembler::ECMA262ToInt32(Register result, |
| 2534 DoubleRegister input, | 2478 DoubleRegister input, |
| 2535 Register scratch1, | 2479 Register scratch1, |
| 2536 Register scratch2, | 2480 Register scratch2, |
| 2537 ECMA262ToInt32Result format) { | 2481 ECMA262ToInt32Result format) { |
| 2538 ASSERT(!AreAliased(result, scratch1, scratch2)); | 2482 ASSERT(!AreAliased(result, scratch1, scratch2)); |
| 2539 ASSERT(result.Is64Bits() && scratch1.Is64Bits() && scratch2.Is64Bits()); | 2483 ASSERT(result.Is64Bits() && scratch1.Is64Bits() && scratch2.Is64Bits()); |
| (...skipping 2301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4841 } | 4785 } |
| 4842 } | 4786 } |
| 4843 | 4787 |
| 4844 | 4788 |
| 4845 #undef __ | 4789 #undef __ |
| 4846 | 4790 |
| 4847 | 4791 |
| 4848 } } // namespace v8::internal | 4792 } } // namespace v8::internal |
| 4849 | 4793 |
| 4850 #endif // V8_TARGET_ARCH_A64 | 4794 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |