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

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: 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
« src/parser.cc ('K') | « 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
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
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
OLDNEW
« src/parser.cc ('K') | « src/x64/macro-assembler-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698