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 |
2468 void MacroAssembler::Throw(Register value) { | 2469 void MacroAssembler::Throw(Register value) { |
2469 // Adjust this code if not the case. | 2470 // Adjust this code if not the case. |
2470 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2471 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
2471 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 2472 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2472 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 2473 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
2473 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 2474 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
2474 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 2475 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
2475 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 2476 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
2476 // Keep thrown value in rax. | 2477 |
2478 // The exception is expected in rax. | |
2477 if (!value.is(rax)) { | 2479 if (!value.is(rax)) { |
2478 movq(rax, value); | 2480 movq(rax, value); |
2479 } | 2481 } |
2482 // Drop the stack pointer to the top of the top handler. | |
2483 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | |
2484 movq(rsp, ExternalOperand(handler_address)); | |
2485 // Restore the next handler. | |
2486 pop(ExternalOperand(handler_address)); | |
2480 | 2487 |
2481 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | 2488 // Remove the code object and state, compute the handler address in rdi. |
2482 Operand handler_operand = ExternalOperand(handler_address); | 2489 pop(rdi); // Code object. |
2483 movq(rsp, handler_operand); | 2490 pop(rdx); // Offset and state. |
2484 // get next in chain | 2491 // The handler table is a fixed array of (smi-tagged) code offsets. |
2485 pop(handler_operand); | 2492 movq(rbx, FieldOperand(rdi, Code::kHandlerTableOffset)); |
2493 shr(rdx, Immediate(StackHandler::kKindWidth)); | |
2494 movq(rdx, FieldOperand(rbx, rdx, times_8, FixedArray::kHeaderSize)); | |
2495 SmiToInteger64(rdx, rdx); | |
2496 lea(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize)); | |
2497 | |
2498 // Restore the context and frame pointer. | |
2486 pop(rsi); // Context. | 2499 pop(rsi); // Context. |
2487 pop(rbp); // Frame pointer. | 2500 pop(rbp); // Frame pointer. |
2488 pop(rdx); // State. | |
2489 | 2501 |
2490 // If the handler is a JS frame, restore the context to the frame. | 2502 // 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 | 2503 // (kind == ENTRY) == (rbp == 0) == (rsi == 0), so we could test either |
2492 // of them. | 2504 // rbp or rsi. |
2493 Label skip; | 2505 Label skip; |
2494 cmpq(rdx, Immediate(StackHandler::ENTRY)); | 2506 testq(rsi, rsi); |
2495 j(equal, &skip, Label::kNear); | 2507 j(zero, &skip, Label::kNear); |
2496 movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); | 2508 movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); |
2497 bind(&skip); | 2509 bind(&skip); |
2498 | 2510 |
2499 ret(0); | 2511 // Jump to the handler code. |
2512 jmp(rdi); | |
2500 } | 2513 } |
2501 | 2514 |
2502 | 2515 |
2503 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 2516 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
2504 Register value) { | 2517 Register value) { |
2505 // Adjust this code if not the case. | 2518 // Adjust this code if not the case. |
2506 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2519 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
2507 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 2520 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
2508 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 1 * kPointerSize); | 2521 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
2509 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 2522 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
2510 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize); | 2523 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
2511 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize); | 2524 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
2512 | 2525 |
2513 // The exception is expected in rax. | 2526 // The exception is expected in rax. |
2514 if (type == OUT_OF_MEMORY) { | 2527 if (type == OUT_OF_MEMORY) { |
2515 // Set external caught exception to false. | 2528 // Set external caught exception to false. |
2516 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, | 2529 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, |
2517 isolate()); | 2530 isolate()); |
2518 Set(rax, static_cast<int64_t>(false)); | 2531 Set(rax, static_cast<int64_t>(false)); |
2519 Store(external_caught, rax); | 2532 Store(external_caught, rax); |
2520 | 2533 |
2521 // Set pending exception and rax to out of memory exception. | 2534 // Set pending exception and rax to out of memory exception. |
2522 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 2535 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
2523 isolate()); | 2536 isolate()); |
2524 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); | 2537 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
2525 Store(pending_exception, rax); | 2538 Store(pending_exception, rax); |
2526 } else if (!value.is(rax)) { | 2539 } else if (!value.is(rax)) { |
2527 movq(rax, value); | 2540 movq(rax, value); |
2528 } | 2541 } |
2529 | 2542 |
2530 // Drop the stack pointer to the top of the top stack handler. | 2543 // Drop the stack pointer to the top of the top stack handler. |
2531 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); | 2544 ExternalReference handler_address(Isolate::kHandlerAddress, isolate()); |
2532 Load(rsp, handler_address); | 2545 Load(rsp, handler_address); |
2533 | 2546 |
2534 // Unwind the handlers until the top ENTRY handler is found. | 2547 // Unwind the handlers until the top ENTRY handler is found. |
2535 Label fetch_next, check_kind; | 2548 Label fetch_next, check_kind; |
2536 jmp(&check_kind, Label::kNear); | 2549 jmp(&check_kind, Label::kNear); |
2537 bind(&fetch_next); | 2550 bind(&fetch_next); |
2538 movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset)); | 2551 movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset)); |
2539 | 2552 |
2540 bind(&check_kind); | 2553 bind(&check_kind); |
2541 cmpq(Operand(rsp, StackHandlerConstants::kStateOffset), | 2554 STATIC_ASSERT(StackHandler::ENTRY == 0); |
2542 Immediate(StackHandler::ENTRY)); | 2555 testl(Operand(rsp, StackHandlerConstants::kStateOffset), |
2543 j(not_equal, &fetch_next); | 2556 Immediate(StackHandler::KindField::kMask)); |
2557 j(not_zero, &fetch_next); | |
2544 | 2558 |
2545 // Set the top handler address to next handler past the top ENTRY handler. | 2559 // Set the top handler address to next handler past the top ENTRY handler. |
2546 pop(ExternalOperand(handler_address)); | 2560 pop(ExternalOperand(handler_address)); |
2547 | 2561 |
2548 // Clear the context and frame pointer (0 was saved in the handler), and | 2562 // Remove the code object and state, compute the handler address in rdi. |
2549 // discard the state. | 2563 pop(rdi); // Code object. |
2564 pop(rdx); // Offset and state. | |
2565 // The handler table is a fixed array of (smi-tagged) code offsets. | |
2566 movq(rbx, FieldOperand(rdi, Code::kHandlerTableOffset)); | |
2567 shr(rdx, Immediate(StackHandler::kKindWidth)); | |
2568 movq(rdx, FieldOperand(rbx, rdx, times_8, FixedArray::kHeaderSize)); | |
2569 SmiToInteger64(rdx, rdx); | |
2570 lea(rdi, FieldOperand(rdi, rdx, times_1, Code::kHeaderSize)); | |
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 // Jump to the handler code. |
2577 jmp(rdi); | |
Vyacheslav Egorov (Chromium)
2011/11/10 19:01:04
Try to share code with throw.
| |
2555 } | 2578 } |
2556 | 2579 |
2557 | 2580 |
2558 void MacroAssembler::Ret() { | 2581 void MacroAssembler::Ret() { |
2559 ret(0); | 2582 ret(0); |
2560 } | 2583 } |
2561 | 2584 |
2562 | 2585 |
2563 void MacroAssembler::Ret(int bytes_dropped, Register scratch) { | 2586 void MacroAssembler::Ret(int bytes_dropped, Register scratch) { |
2564 if (is_uint16(bytes_dropped)) { | 2587 if (is_uint16(bytes_dropped)) { |
(...skipping 1655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4220 | 4243 |
4221 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); | 4244 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); |
4222 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); | 4245 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); |
4223 | 4246 |
4224 bind(&done); | 4247 bind(&done); |
4225 } | 4248 } |
4226 | 4249 |
4227 } } // namespace v8::internal | 4250 } } // namespace v8::internal |
4228 | 4251 |
4229 #endif // V8_TARGET_ARCH_X64 | 4252 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |