Small change to stack checks in unoptimized code.

The stack checks include a loop nesting depth encoded in the code stream
after the call to the stack check stub.  Change the code to jump around this
instruction as well as the call when the stack check is OK.

Review URL: http://codereview.chromium.org/6005014

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6204 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 26550605
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -221,10 +221,17 @@ void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { ...@@ -221,10 +221,17 @@ void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
__ b(hs, &ok); __ b(hs, &ok);
StackCheckStub stub; StackCheckStub stub;
__ CallStub(&stub); __ CallStub(&stub);
// Record a mapping of this PC offset to the OSR id. This is used to find
// the AST id from the unoptimized code in order to use it as a key into
// the deoptimization input data found in the optimized code.
RecordStackCheck(stmt->OsrEntryId());
__ bind(&ok); __ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
RecordStackCheck(stmt->OsrEntryId());
} }
......
// Copyright 2010 the V8 project authors. All rights reserved. // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -105,23 +105,25 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -105,23 +105,25 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo, void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo,
Code* replacement_code) { Code* replacement_code) {
// The stack check code matches the pattern (on ia32, for example): // The stack check code matches the pattern:
// //
// cmp esp, <limit> // cmp esp, <limit>
// jae ok // jae ok
// call <stack guard> // call <stack guard>
// test eax, <loop nesting depth>
// ok: ... // ok: ...
// //
// We will patch the code to: // We will patch away the branch so the code is:
// //
// cmp esp, <limit> ;; Not changed // cmp esp, <limit> ;; Not changed
// nop // nop
// nop // nop
// call <on-stack replacment> // call <on-stack replacment>
// test eax, <loop nesting depth>
// ok: // ok:
Address call_target_address = rinfo->pc(); Address call_target_address = rinfo->pc();
ASSERT(*(call_target_address - 3) == 0x73 && // jae ASSERT(*(call_target_address - 3) == 0x73 && // jae
*(call_target_address - 2) == 0x05 && // offset *(call_target_address - 2) == 0x07 && // offset
*(call_target_address - 1) == 0xe8); // call *(call_target_address - 1) == 0xe8); // call
*(call_target_address - 3) = 0x90; // nop *(call_target_address - 3) = 0x90; // nop
*(call_target_address - 2) = 0x90; // nop *(call_target_address - 2) = 0x90; // nop
...@@ -130,12 +132,14 @@ void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo, ...@@ -130,12 +132,14 @@ void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo,
void Deoptimizer::RevertStackCheckCode(RelocInfo* rinfo, Code* check_code) { void Deoptimizer::RevertStackCheckCode(RelocInfo* rinfo, Code* check_code) {
// Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
// restore the conditional branch.
Address call_target_address = rinfo->pc(); Address call_target_address = rinfo->pc();
ASSERT(*(call_target_address - 3) == 0x90 && // nop ASSERT(*(call_target_address - 3) == 0x90 && // nop
*(call_target_address - 2) == 0x90 && // nop *(call_target_address - 2) == 0x90 && // nop
*(call_target_address - 1) == 0xe8); // call *(call_target_address - 1) == 0xe8); // call
*(call_target_address - 3) = 0x73; // jae *(call_target_address - 3) = 0x73; // jae
*(call_target_address - 2) = 0x05; // offset *(call_target_address - 2) = 0x07; // offset
rinfo->set_target_address(check_code->entry()); rinfo->set_target_address(check_code->entry());
} }
......
...@@ -264,16 +264,24 @@ void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { ...@@ -264,16 +264,24 @@ void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
__ j(above_equal, &ok, taken); __ j(above_equal, &ok, taken);
StackCheckStub stub; StackCheckStub stub;
__ CallStub(&stub); __ CallStub(&stub);
__ bind(&ok); // Record a mapping of this PC offset to the OSR id. This is used to find
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); // the AST id from the unoptimized code in order to use it as a key into
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); // the deoptimization input data found in the optimized code.
RecordStackCheck(stmt->OsrEntryId()); RecordStackCheck(stmt->OsrEntryId());
// Loop stack checks can be patched to perform on-stack
// replacement. In order to decide whether or not to perform OSR we // Loop stack checks can be patched to perform on-stack replacement. In
// embed the loop depth in a test instruction after the call so we // order to decide whether or not to perform OSR we embed the loop depth
// can extract it from the OSR builtin. // in a test instruction after the call so we can extract it from the OSR
// builtin.
ASSERT(loop_depth() > 0); ASSERT(loop_depth() > 0);
__ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker))); __ test(eax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
__ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
} }
......
...@@ -210,10 +210,17 @@ void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { ...@@ -210,10 +210,17 @@ void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
__ j(above_equal, &ok); __ j(above_equal, &ok);
StackCheckStub stub; StackCheckStub stub;
__ CallStub(&stub); __ CallStub(&stub);
// Record a mapping of this PC offset to the OSR id. This is used to find
// the AST id from the unoptimized code in order to use it as a key into
// the deoptimization input data found in the optimized code.
RecordStackCheck(stmt->OsrEntryId());
__ bind(&ok); __ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
RecordStackCheck(stmt->OsrEntryId());
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment