OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2410 movq(dst, SafepointRegisterSlot(src)); | 2410 movq(dst, SafepointRegisterSlot(src)); |
2411 } | 2411 } |
2412 | 2412 |
2413 | 2413 |
2414 Operand MacroAssembler::SafepointRegisterSlot(Register reg) { | 2414 Operand MacroAssembler::SafepointRegisterSlot(Register reg) { |
2415 return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); | 2415 return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); |
2416 } | 2416 } |
2417 | 2417 |
2418 | 2418 |
2419 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 2419 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
2420 HandlerType type) { | 2420 HandlerType type, |
| 2421 int handler_index) { |
2421 // Adjust this code if not the case. | 2422 // Adjust this code if not the case. |
2422 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2423 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
2423 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 2424 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2424 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 2425 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
2425 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 2426 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
2426 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 2427 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
2427 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 2428 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
2428 | 2429 |
2429 // The pc (return address) is already on TOS. This code pushes state, | 2430 // We will build up the handler from the bottom by pushing on the stack. |
2430 // frame pointer, context, and current handler. | 2431 // First compute the state and push the frame pointer and context. |
| 2432 unsigned state = StackHandler::OffsetField::encode(handler_index); |
2431 if (try_location == IN_JAVASCRIPT) { | 2433 if (try_location == IN_JAVASCRIPT) { |
2432 if (type == TRY_CATCH_HANDLER) { | |
2433 push(Immediate(StackHandler::TRY_CATCH)); | |
2434 } else { | |
2435 push(Immediate(StackHandler::TRY_FINALLY)); | |
2436 } | |
2437 push(rbp); | 2434 push(rbp); |
2438 push(rsi); | 2435 push(rsi); |
| 2436 state |= (type == TRY_CATCH_HANDLER) |
| 2437 ? StackHandler::KindField::encode(StackHandler::TRY_CATCH) |
| 2438 : StackHandler::KindField::encode(StackHandler::TRY_FINALLY); |
2439 } else { | 2439 } else { |
2440 ASSERT(try_location == IN_JS_ENTRY); | 2440 ASSERT(try_location == IN_JS_ENTRY); |
2441 // The frame pointer does not point to a JS frame so we save NULL | 2441 // The frame pointer does not point to a JS frame so we save NULL for |
2442 // for rbp. We expect the code throwing an exception to check rbp | 2442 // rbp. We expect the code throwing an exception to check rbp before |
2443 // before dereferencing it to restore the context. | 2443 // dereferencing it to restore the context. |
2444 push(Immediate(StackHandler::ENTRY)); | |
2445 push(Immediate(0)); // NULL frame pointer. | 2444 push(Immediate(0)); // NULL frame pointer. |
2446 Push(Smi::FromInt(0)); // No context. | 2445 Push(Smi::FromInt(0)); // No context. |
| 2446 state |= StackHandler::KindField::encode(StackHandler::ENTRY); |
2447 } | 2447 } |
2448 // Save the current handler. | 2448 |
2449 Operand handler_operand = | 2449 // Push the state and the code object. |
2450 ExternalOperand(ExternalReference(Isolate::kHandlerAddress, isolate())); | 2450 push(Immediate(state)); |
2451 push(handler_operand); | 2451 Push(CodeObject()); |
2452 // Link this handler. | 2452 |
2453 movq(handler_operand, rsp); | 2453 // Link the current handler as the next handler. |
| 2454 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
| 2455 push(ExternalOperand(handler_address)); |
| 2456 // Set this new handler as the current one. |
| 2457 movq(ExternalOperand(handler_address), rsp); |
2454 } | 2458 } |
2455 | 2459 |
2456 | 2460 |
2457 void MacroAssembler::PopTryHandler() { | 2461 void MacroAssembler::PopTryHandler() { |
2458 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 2462 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2459 // Unlink this handler. | 2463 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
2460 Operand handler_operand = | 2464 pop(ExternalOperand(handler_address)); |
2461 ExternalOperand(ExternalReference(Isolate::kHandlerAddress, isolate())); | |
2462 pop(handler_operand); | |
2463 // Remove the remaining fields. | |
2464 addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); | 2465 addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); |
2465 } | 2466 } |
2466 | 2467 |
2467 | 2468 |
| 2469 void MacroAssembler::JumpToHandlerEntry() { |
| 2470 // Compute the handler entry address and jump to it. The handler table is |
| 2471 // a fixed array of (smi-tagged) code offsets. |
| 2472 // rax = exception, rdi = code object, rdx = state. |
| 2473 movq(rbx, FieldOperand(rdi, Code::kHandlerTableOffset)); |
| 2474 shr(rdx, Immediate(StackHandler::kKindWidth)); |
| 2475 movq(rdx, FieldOperand(rbx, rdx, times_8, FixedArray::kHeaderSize)); |
| 2476 SmiToInteger64(rdx, rdx); |
| 2477 lea(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize)); |
| 2478 jmp(rdi); |
| 2479 } |
| 2480 |
| 2481 |
2468 void MacroAssembler::Throw(Register value) { | 2482 void MacroAssembler::Throw(Register value) { |
2469 // Adjust this code if not the case. | 2483 // Adjust this code if not the case. |
2470 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2484 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
2471 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 2485 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2472 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 2486 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
2473 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 2487 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
2474 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 2488 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
2475 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 2489 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
2476 // Keep thrown value in rax. | 2490 |
| 2491 // The exception is expected in rax. |
2477 if (!value.is(rax)) { | 2492 if (!value.is(rax)) { |
2478 movq(rax, value); | 2493 movq(rax, value); |
2479 } | 2494 } |
| 2495 // Drop the stack pointer to the top of the top handler. |
| 2496 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
| 2497 movq(rsp, ExternalOperand(handler_address)); |
| 2498 // Restore the next handler. |
| 2499 pop(ExternalOperand(handler_address)); |
2480 | 2500 |
2481 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | 2501 // Remove the code object and state, compute the handler address in rdi. |
2482 Operand handler_operand = ExternalOperand(handler_address); | 2502 pop(rdi); // Code object. |
2483 movq(rsp, handler_operand); | 2503 pop(rdx); // Offset and state. |
2484 // get next in chain | 2504 |
2485 pop(handler_operand); | 2505 // Restore the context and frame pointer. |
2486 pop(rsi); // Context. | 2506 pop(rsi); // Context. |
2487 pop(rbp); // Frame pointer. | 2507 pop(rbp); // Frame pointer. |
2488 pop(rdx); // State. | |
2489 | 2508 |
2490 // If the handler is a JS frame, restore the context to the frame. | 2509 // If the handler is a JS frame, restore the context to the frame. |
2491 // (rdx == ENTRY) == (rbp == 0) == (rsi == 0), so we could test any | 2510 // (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either |
2492 // of them. | 2511 // rbp or rsi. |
2493 Label skip; | 2512 Label skip; |
2494 cmpq(rdx, Immediate(StackHandler::ENTRY)); | 2513 testq(rsi, rsi); |
2495 j(equal, &skip, Label::kNear); | 2514 j(zero, &skip, Label::kNear); |
2496 movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); | 2515 movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); |
2497 bind(&skip); | 2516 bind(&skip); |
2498 | 2517 |
2499 ret(0); | 2518 JumpToHandlerEntry(); |
2500 } | 2519 } |
2501 | 2520 |
2502 | 2521 |
2503 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 2522 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
2504 Register value) { | 2523 Register value) { |
2505 // Adjust this code if not the case. | 2524 // Adjust this code if not the case. |
2506 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2525 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
2507 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 2526 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2508 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 2527 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
2509 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 2528 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
2510 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 2529 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
2511 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 2530 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
2512 | 2531 |
2513 // The exception is expected in rax. | 2532 // The exception is expected in rax. |
2514 if (type == OUT_OF_MEMORY) { | 2533 if (type == OUT_OF_MEMORY) { |
2515 // Set external caught exception to false. | 2534 // Set external caught exception to false. |
2516 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, | 2535 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, |
2517 isolate()); | 2536 isolate()); |
2518 Set(rax, static_cast<int64_t>(false)); | 2537 Set(rax, static_cast<int64_t>(false)); |
2519 Store(external_caught, rax); | 2538 Store(external_caught, rax); |
2520 | 2539 |
2521 // Set pending exception and rax to out of memory exception. | 2540 // Set pending exception and rax to out of memory exception. |
2522 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 2541 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
2523 isolate()); | 2542 isolate()); |
2524 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); | 2543 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
2525 Store(pending_exception, rax); | 2544 Store(pending_exception, rax); |
2526 } else if (!value.is(rax)) { | 2545 } else if (!value.is(rax)) { |
2527 movq(rax, value); | 2546 movq(rax, value); |
2528 } | 2547 } |
2529 | 2548 |
2530 // Drop the stack pointer to the top of the top stack handler. | 2549 // Drop the stack pointer to the top of the top stack handler. |
2531 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | 2550 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
2532 Load(rsp, handler_address); | 2551 Load(rsp, handler_address); |
2533 | 2552 |
2534 // Unwind the handlers until the top ENTRY handler is found. | 2553 // Unwind the handlers until the top ENTRY handler is found. |
2535 Label fetch_next, check_kind; | 2554 Label fetch_next, check_kind; |
2536 jmp(&check_kind, Label::kNear); | 2555 jmp(&check_kind, Label::kNear); |
2537 bind(&fetch_next); | 2556 bind(&fetch_next); |
2538 movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset)); | 2557 movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset)); |
2539 | 2558 |
2540 bind(&check_kind); | 2559 bind(&check_kind); |
2541 cmpq(Operand(rsp, StackHandlerConstants::kStateOffset), | 2560 STATIC_ASSERT(StackHandler::ENTRY == 0); |
2542 Immediate(StackHandler::ENTRY)); | 2561 testl(Operand(rsp, StackHandlerConstants::kStateOffset), |
2543 j(not_equal, &fetch_next); | 2562 Immediate(StackHandler::KindField::kMask)); |
| 2563 j(not_zero, &fetch_next); |
2544 | 2564 |
2545 // Set the top handler address to next handler past the top ENTRY handler. | 2565 // Set the top handler address to next handler past the top ENTRY handler. |
2546 pop(ExternalOperand(handler_address)); | 2566 pop(ExternalOperand(handler_address)); |
2547 | 2567 |
2548 // Clear the context and frame pointer (0 was saved in the handler), and | 2568 // Remove the code object and state, compute the handler address in rdi. |
2549 // discard the state. | 2569 pop(rdi); // Code object. |
| 2570 pop(rdx); // Offset and state. |
| 2571 |
| 2572 // Clear the context pointer and frame pointer (0 was saved in the handler). |
2550 pop(rsi); | 2573 pop(rsi); |
2551 pop(rbp); | 2574 pop(rbp); |
2552 pop(rdx); // State. | |
2553 | 2575 |
2554 ret(0); | 2576 JumpToHandlerEntry(); |
2555 } | 2577 } |
2556 | 2578 |
2557 | 2579 |
2558 void MacroAssembler::Ret() { | 2580 void MacroAssembler::Ret() { |
2559 ret(0); | 2581 ret(0); |
2560 } | 2582 } |
2561 | 2583 |
2562 | 2584 |
2563 void MacroAssembler::Ret(int bytes_dropped, Register scratch) { | 2585 void MacroAssembler::Ret(int bytes_dropped, Register scratch) { |
2564 if (is_uint16(bytes_dropped)) { | 2586 if (is_uint16(bytes_dropped)) { |
(...skipping 1655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4220 | 4242 |
4221 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); | 4243 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); |
4222 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); | 4244 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); |
4223 | 4245 |
4224 bind(&done); | 4246 bind(&done); |
4225 } | 4247 } |
4226 | 4248 |
4227 } } // namespace v8::internal | 4249 } } // namespace v8::internal |
4228 | 4250 |
4229 #endif // V8_TARGET_ARCH_X64 | 4251 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |