Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: src/x64/macro-assembler-x64.cc

Issue 8462010: Add a level of indirection to exception handler addresses. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Incorporate review changes. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/macro-assembler-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698