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