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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 119358: Change the IA32 stack handler layout so that the handler address does... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 6 months 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/frames.cc ('k') | src/ia32/frames-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 3234 matching lines...) Expand 10 before | Expand all | Expand 10 after
3245 has_unlinks = has_unlinks || shadows[i]->is_linked(); 3245 has_unlinks = has_unlinks || shadows[i]->is_linked();
3246 } 3246 }
3247 function_return_is_shadowed_ = function_return_was_shadowed; 3247 function_return_is_shadowed_ = function_return_was_shadowed;
3248 3248
3249 // Get an external reference to the handler address. 3249 // Get an external reference to the handler address.
3250 ExternalReference handler_address(Top::k_handler_address); 3250 ExternalReference handler_address(Top::k_handler_address);
3251 3251
3252 // Make sure that there's nothing left on the stack above the 3252 // Make sure that there's nothing left on the stack above the
3253 // handler structure. 3253 // handler structure.
3254 if (FLAG_debug_code) { 3254 if (FLAG_debug_code) {
3255 ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
3255 __ mov(eax, Operand::StaticVariable(handler_address)); 3256 __ mov(eax, Operand::StaticVariable(handler_address));
3256 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement));
3257 __ cmp(esp, Operand(eax)); 3257 __ cmp(esp, Operand(eax));
3258 __ Assert(equal, "stack pointer should point to top handler"); 3258 __ Assert(equal, "stack pointer should point to top handler");
3259 } 3259 }
3260 3260
3261 // If we can fall off the end of the try block, unlink from try chain. 3261 // If we can fall off the end of the try block, unlink from try chain.
3262 if (has_valid_frame()) { 3262 if (has_valid_frame()) {
3263 // The next handler address is on top of the frame. Unlink from 3263 // The next handler address is on top of the frame. Unlink from
3264 // the handler list and drop the rest of this handler from the 3264 // the handler list and drop the rest of this handler from the
3265 // frame. 3265 // frame.
3266 ASSERT(StackHandlerConstants::kNextOffset == 0);
3266 frame_->EmitPop(Operand::StaticVariable(handler_address)); 3267 frame_->EmitPop(Operand::StaticVariable(handler_address));
3267 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 3268 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
3268 if (has_unlinks) { 3269 if (has_unlinks) {
3269 exit.Jump(); 3270 exit.Jump();
3270 } 3271 }
3271 } 3272 }
3272 3273
3273 // Generate unlink code for the (formerly) shadowing targets that 3274 // Generate unlink code for the (formerly) shadowing targets that
3274 // have been jumped to. Deallocate each shadow target. 3275 // have been jumped to. Deallocate each shadow target.
3275 Result return_value; 3276 Result return_value;
3276 for (int i = 0; i < shadows.length(); i++) { 3277 for (int i = 0; i < shadows.length(); i++) {
3277 if (shadows[i]->is_linked()) { 3278 if (shadows[i]->is_linked()) {
3278 // Unlink from try chain; be careful not to destroy the TOS if 3279 // Unlink from try chain; be careful not to destroy the TOS if
3279 // there is one. 3280 // there is one.
3280 if (i == kReturnShadowIndex) { 3281 if (i == kReturnShadowIndex) {
3281 shadows[i]->Bind(&return_value); 3282 shadows[i]->Bind(&return_value);
3282 return_value.ToRegister(eax); 3283 return_value.ToRegister(eax);
3283 } else { 3284 } else {
3284 shadows[i]->Bind(); 3285 shadows[i]->Bind();
3285 } 3286 }
3286 // Because we can be jumping here (to spilled code) from 3287 // Because we can be jumping here (to spilled code) from
3287 // unspilled code, we need to reestablish a spilled frame at 3288 // unspilled code, we need to reestablish a spilled frame at
3288 // this block. 3289 // this block.
3289 frame_->SpillAll(); 3290 frame_->SpillAll();
3290 3291
3291 // Reload sp from the top handler, because some statements that we 3292 // Reload sp from the top handler, because some statements that we
3292 // break from (eg, for...in) may have left stuff on the stack. 3293 // break from (eg, for...in) may have left stuff on the stack.
3293 __ mov(edx, Operand::StaticVariable(handler_address)); 3294 ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
3294 const int kNextOffset = StackHandlerConstants::kNextOffset + 3295 __ mov(esp, Operand::StaticVariable(handler_address));
3295 StackHandlerConstants::kAddressDisplacement;
3296 __ lea(esp, Operand(edx, kNextOffset));
3297 frame_->Forget(frame_->height() - handler_height); 3296 frame_->Forget(frame_->height() - handler_height);
3298 3297
3298 ASSERT(StackHandlerConstants::kNextOffset == 0);
3299 frame_->EmitPop(Operand::StaticVariable(handler_address)); 3299 frame_->EmitPop(Operand::StaticVariable(handler_address));
3300 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 3300 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
3301 // next_sp popped.
3302 3301
3303 if (i == kReturnShadowIndex) { 3302 if (i == kReturnShadowIndex) {
3304 if (!function_return_is_shadowed_) frame_->PrepareForReturn(); 3303 if (!function_return_is_shadowed_) frame_->PrepareForReturn();
3305 shadows[i]->other_target()->Jump(&return_value); 3304 shadows[i]->other_target()->Jump(&return_value);
3306 } else { 3305 } else {
3307 shadows[i]->other_target()->Jump(); 3306 shadows[i]->other_target()->Jump();
3308 } 3307 }
3309 } 3308 }
3310 } 3309 }
3311 3310
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3376 function_return_is_shadowed_ = function_return_was_shadowed; 3375 function_return_is_shadowed_ = function_return_was_shadowed;
3377 3376
3378 // Get an external reference to the handler address. 3377 // Get an external reference to the handler address.
3379 ExternalReference handler_address(Top::k_handler_address); 3378 ExternalReference handler_address(Top::k_handler_address);
3380 3379
3381 // If we can fall off the end of the try block, unlink from the try 3380 // If we can fall off the end of the try block, unlink from the try
3382 // chain and set the state on the frame to FALLING. 3381 // chain and set the state on the frame to FALLING.
3383 if (has_valid_frame()) { 3382 if (has_valid_frame()) {
3384 // The next handler address is on top of the frame. 3383 // The next handler address is on top of the frame.
3385 ASSERT(StackHandlerConstants::kNextOffset == 0); 3384 ASSERT(StackHandlerConstants::kNextOffset == 0);
3386 frame_->EmitPop(eax); 3385 frame_->EmitPop(Operand::StaticVariable(handler_address));
3387 __ mov(Operand::StaticVariable(handler_address), eax);
3388 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 3386 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
3389 3387
3390 // Fake a top of stack value (unneeded when FALLING) and set the 3388 // Fake a top of stack value (unneeded when FALLING) and set the
3391 // state in ecx, then jump around the unlink blocks if any. 3389 // state in ecx, then jump around the unlink blocks if any.
3392 frame_->EmitPush(Immediate(Factory::undefined_value())); 3390 frame_->EmitPush(Immediate(Factory::undefined_value()));
3393 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); 3391 __ Set(ecx, Immediate(Smi::FromInt(FALLING)));
3394 if (nof_unlinks > 0) { 3392 if (nof_unlinks > 0) {
3395 finally_block.Jump(); 3393 finally_block.Jump();
3396 } 3394 }
3397 } 3395 }
(...skipping 13 matching lines...) Expand all
3411 shadows[i]->Bind(); 3409 shadows[i]->Bind();
3412 } 3410 }
3413 // Because we can be jumping here (to spilled code) from 3411 // Because we can be jumping here (to spilled code) from
3414 // unspilled code, we need to reestablish a spilled frame at 3412 // unspilled code, we need to reestablish a spilled frame at
3415 // this block. 3413 // this block.
3416 frame_->SpillAll(); 3414 frame_->SpillAll();
3417 3415
3418 // Reload sp from the top handler, because some statements that 3416 // Reload sp from the top handler, because some statements that
3419 // we break from (eg, for...in) may have left stuff on the 3417 // we break from (eg, for...in) may have left stuff on the
3420 // stack. 3418 // stack.
3421 __ mov(edx, Operand::StaticVariable(handler_address)); 3419 ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
3422 const int kNextOffset = StackHandlerConstants::kNextOffset + 3420 __ mov(esp, Operand::StaticVariable(handler_address));
3423 StackHandlerConstants::kAddressDisplacement;
3424 __ lea(esp, Operand(edx, kNextOffset));
3425 frame_->Forget(frame_->height() - handler_height); 3421 frame_->Forget(frame_->height() - handler_height);
3426 3422
3427 // Unlink this handler and drop it from the frame. 3423 // Unlink this handler and drop it from the frame.
3424 ASSERT(StackHandlerConstants::kNextOffset == 0);
3428 frame_->EmitPop(Operand::StaticVariable(handler_address)); 3425 frame_->EmitPop(Operand::StaticVariable(handler_address));
3429 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 3426 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
3430 3427
3431 if (i == kReturnShadowIndex) { 3428 if (i == kReturnShadowIndex) {
3432 // If this target shadowed the function return, materialize 3429 // If this target shadowed the function return, materialize
3433 // the return value on the stack. 3430 // the return value on the stack.
3434 frame_->EmitPush(eax); 3431 frame_->EmitPush(eax);
3435 } else { 3432 } else {
3436 // Fake TOS for targets that shadowed breaks and continues. 3433 // Fake TOS for targets that shadowed breaks and continues.
3437 frame_->EmitPush(Immediate(Factory::undefined_value())); 3434 frame_->EmitPush(Immediate(Factory::undefined_value()));
(...skipping 3515 matching lines...) Expand 10 before | Expand all | Expand 10 after
6953 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 6950 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
6954 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 6951 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
6955 __ jmp(adaptor, RelocInfo::CODE_TARGET); 6952 __ jmp(adaptor, RelocInfo::CODE_TARGET);
6956 } 6953 }
6957 6954
6958 6955
6959 6956
6960 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 6957 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
6961 // Adjust this code if not the case. 6958 // Adjust this code if not the case.
6962 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 6959 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
6960
6961 // Drop the sp to the top of the handler.
6962 ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
6963 ExternalReference handler_address(Top::k_handler_address); 6963 ExternalReference handler_address(Top::k_handler_address);
6964 __ mov(edx, Operand::StaticVariable(handler_address)); 6964 __ mov(esp, Operand::StaticVariable(handler_address));
6965 // Get next in chain. 6965
6966 __ mov(ecx, Operand(edx, StackHandlerConstants::kAddressDisplacement)); 6966 // Restore next handler and frame pointer, discard handler state.
6967 __ mov(Operand::StaticVariable(handler_address), ecx); 6967 ASSERT(StackHandlerConstants::kNextOffset == 0);
6968 __ mov(esp, Operand(edx)); 6968 __ pop(Operand::StaticVariable(handler_address));
6969 ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
6969 __ pop(ebp); 6970 __ pop(ebp);
6970 __ pop(edx); // Remove state. 6971 __ pop(edx); // Remove state.
6971 6972
6972 // Before returning we restore the context from the frame pointer if not NULL. 6973 // Before returning we restore the context from the frame pointer if not NULL.
6973 // The frame pointer is NULL in the exception handler of a JS entry frame. 6974 // The frame pointer is NULL in the exception handler of a JS entry frame.
6974 __ xor_(esi, Operand(esi)); // tentatively set context pointer to NULL 6975 __ xor_(esi, Operand(esi)); // tentatively set context pointer to NULL
6975 Label skip; 6976 Label skip;
6976 __ cmp(ebp, 0); 6977 __ cmp(ebp, 0);
6977 __ j(equal, &skip, not_taken); 6978 __ j(equal, &skip, not_taken);
6978 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 6979 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6979 __ bind(&skip); 6980 __ bind(&skip);
6980 6981
6982 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
6981 __ ret(0); 6983 __ ret(0);
6982 } 6984 }
6983 6985
6984 6986
6985 void CEntryStub::GenerateCore(MacroAssembler* masm, 6987 void CEntryStub::GenerateCore(MacroAssembler* masm,
6986 Label* throw_normal_exception, 6988 Label* throw_normal_exception,
6987 Label* throw_out_of_memory_exception, 6989 Label* throw_out_of_memory_exception,
6988 StackFrame::Type frame_type, 6990 StackFrame::Type frame_type,
6989 bool do_gc, 6991 bool do_gc,
6990 bool always_allocate_scope) { 6992 bool always_allocate_scope) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
7059 7061
7060 // Retry. 7062 // Retry.
7061 __ bind(&retry); 7063 __ bind(&retry);
7062 } 7064 }
7063 7065
7064 7066
7065 void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { 7067 void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
7066 // Adjust this code if not the case. 7068 // Adjust this code if not the case.
7067 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); 7069 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
7068 7070
7069 // Fetch top stack handler. 7071 // Drop sp to the top stack handler.
7072 ASSERT(StackHandlerConstants::kAddressDisplacement == 0);
7070 ExternalReference handler_address(Top::k_handler_address); 7073 ExternalReference handler_address(Top::k_handler_address);
7071 __ mov(edx, Operand::StaticVariable(handler_address)); 7074 __ mov(esp, Operand::StaticVariable(handler_address));
7072 7075
7073 // Unwind the handlers until the ENTRY handler is found. 7076 // Unwind the handlers until the ENTRY handler is found.
7074 Label loop, done; 7077 Label loop, done;
7075 __ bind(&loop); 7078 __ bind(&loop);
7076 // Load the type of the current stack handler. 7079 // Load the type of the current stack handler.
7077 const int kStateOffset = StackHandlerConstants::kAddressDisplacement + 7080 const int kStateOffset = StackHandlerConstants::kStateOffset;
7078 StackHandlerConstants::kStateOffset; 7081 __ cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY));
7079 __ cmp(Operand(edx, kStateOffset), Immediate(StackHandler::ENTRY));
7080 __ j(equal, &done); 7082 __ j(equal, &done);
7081 // Fetch the next handler in the list. 7083 // Fetch the next handler in the list.
7082 const int kNextOffset = StackHandlerConstants::kAddressDisplacement + 7084 const int kNextOffset = StackHandlerConstants::kNextOffset;
7083 StackHandlerConstants::kNextOffset; 7085 __ mov(esp, Operand(esp, kNextOffset));
7084 __ mov(edx, Operand(edx, kNextOffset));
7085 __ jmp(&loop); 7086 __ jmp(&loop);
7086 __ bind(&done); 7087 __ bind(&done);
7087 7088
7088 // Set the top handler address to next handler past the current ENTRY handler. 7089 // Set the top handler address to next handler past the current ENTRY handler.
7089 __ mov(eax, Operand(edx, kNextOffset)); 7090 ASSERT(StackHandlerConstants::kNextOffset == 0);
7090 __ mov(Operand::StaticVariable(handler_address), eax); 7091 __ pop(Operand::StaticVariable(handler_address));
7091 7092
7092 // Set external caught exception to false. 7093 // Set external caught exception to false.
7094 ExternalReference external_caught(Top::k_external_caught_exception_address);
7093 __ mov(eax, false); 7095 __ mov(eax, false);
7094 ExternalReference external_caught(Top::k_external_caught_exception_address);
7095 __ mov(Operand::StaticVariable(external_caught), eax); 7096 __ mov(Operand::StaticVariable(external_caught), eax);
7096 7097
7097 // Set pending exception and eax to out of memory exception. 7098 // Set pending exception and eax to out of memory exception.
7099 ExternalReference pending_exception(Top::k_pending_exception_address);
7098 __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); 7100 __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
7099 ExternalReference pending_exception(Top::k_pending_exception_address);
7100 __ mov(Operand::StaticVariable(pending_exception), eax); 7101 __ mov(Operand::StaticVariable(pending_exception), eax);
7101 7102
7102 // Restore the stack to the address of the ENTRY handler
7103 __ mov(esp, Operand(edx));
7104
7105 // Clear the context pointer; 7103 // Clear the context pointer;
7106 __ xor_(esi, Operand(esi)); 7104 __ xor_(esi, Operand(esi));
7107 7105
7108 // Restore registers from handler. 7106 // Restore fp from handler and discard handler state.
7109 __ pop(ebp); // FP 7107 ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize);
7110 __ pop(edx); // State 7108 __ pop(ebp);
7109 __ pop(edx); // State.
7111 7110
7111 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
7112 __ ret(0); 7112 __ ret(0);
7113 } 7113 }
7114 7114
7115 7115
7116 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { 7116 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
7117 // eax: number of arguments including receiver 7117 // eax: number of arguments including receiver
7118 // ebx: pointer to C function (C callee-saved) 7118 // ebx: pointer to C function (C callee-saved)
7119 // ebp: frame pointer (restored after C call) 7119 // ebp: frame pointer (restored after C call)
7120 // esp: stack pointer (restored after C call) 7120 // esp: stack pointer (restored after C call)
7121 // esi: current context (C callee-saved) 7121 // esi: current context (C callee-saved)
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
7220 // Caught exception: Store result (exception) in the pending 7220 // Caught exception: Store result (exception) in the pending
7221 // exception field in the JSEnv and return a failure sentinel. 7221 // exception field in the JSEnv and return a failure sentinel.
7222 ExternalReference pending_exception(Top::k_pending_exception_address); 7222 ExternalReference pending_exception(Top::k_pending_exception_address);
7223 __ mov(Operand::StaticVariable(pending_exception), eax); 7223 __ mov(Operand::StaticVariable(pending_exception), eax);
7224 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception())); 7224 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
7225 __ jmp(&exit); 7225 __ jmp(&exit);
7226 7226
7227 // Invoke: Link this frame into the handler chain. 7227 // Invoke: Link this frame into the handler chain.
7228 __ bind(&invoke); 7228 __ bind(&invoke);
7229 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); 7229 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
7230 __ push(eax); // flush TOS
7231 7230
7232 // Clear any pending exceptions. 7231 // Clear any pending exceptions.
7233 __ mov(edx, 7232 __ mov(edx,
7234 Operand::StaticVariable(ExternalReference::the_hole_value_location())); 7233 Operand::StaticVariable(ExternalReference::the_hole_value_location()));
7235 __ mov(Operand::StaticVariable(pending_exception), edx); 7234 __ mov(Operand::StaticVariable(pending_exception), edx);
7236 7235
7237 // Fake a receiver (NULL). 7236 // Fake a receiver (NULL).
7238 __ push(Immediate(0)); // receiver 7237 __ push(Immediate(0)); // receiver
7239 7238
7240 // Invoke the function by calling through JS entry trampoline 7239 // Invoke the function by calling through JS entry trampoline
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
7335 7334
7336 // Slow-case: Go through the JavaScript implementation. 7335 // Slow-case: Go through the JavaScript implementation.
7337 __ bind(&slow); 7336 __ bind(&slow);
7338 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7337 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7339 } 7338 }
7340 7339
7341 7340
7342 #undef __ 7341 #undef __
7343 7342
7344 } } // namespace v8::internal 7343 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/frames.cc ('k') | src/ia32/frames-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698