Commit 4c8fbaff authored by ager@chromium.org's avatar ager@chromium.org

Move stack check patching to the architecture dependent deoptimizer

files. On ARM it is not enough to iterate the relocation information
because that will only give us access to the constant pool and not to
the place in the instruction stream where the target in the constant
pool is called.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6444 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9c2d52eb
...@@ -112,13 +112,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -112,13 +112,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
} }
void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo, void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code) { Code* replacement_code) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void Deoptimizer::RevertStackCheckCode(RelocInfo* rinfo, Code* check_code) { void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -128,14 +128,17 @@ class Deoptimizer : public Malloced { ...@@ -128,14 +128,17 @@ class Deoptimizer : public Malloced {
static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor* visitor); static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor* visitor);
// Given the relocation info of a call to the stack check stub, patch the // Patch all stack guard checks in the unoptimized code to
// code so as to go unconditionally to the on-stack replacement builtin // unconditionally call replacement_code.
// instead. static void PatchStackCheckCode(Code* unoptimized_code,
static void PatchStackCheckCode(RelocInfo* rinfo, Code* replacement_code); Code* check_code,
Code* replacement_code);
// Given the relocation info of a call to the on-stack replacement
// builtin, patch the code back to the original stack check code. // Change all patched stack guard checks in the unoptimized code
static void RevertStackCheckCode(RelocInfo* rinfo, Code* check_code); // back to a normal stack guard check.
static void RevertStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code);
~Deoptimizer(); ~Deoptimizer();
......
...@@ -106,44 +106,71 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -106,44 +106,71 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
} }
void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo, void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code) { Code* replacement_code) {
// The stack check code matches the pattern: // Iterate the unoptimized code and patch every stack check except at
// // the function entry. This code assumes the function entry stack
// cmp esp, <limit> // check appears first i.e., is not deferred or otherwise reordered.
// jae ok ASSERT(unoptimized_code->kind() == Code::FUNCTION);
// call <stack guard> bool first = true;
// test eax, <loop nesting depth> for (RelocIterator it(unoptimized_code, RelocInfo::kCodeTargetMask);
// ok: ... !it.done();
// it.next()) {
// We will patch away the branch so the code is: RelocInfo* rinfo = it.rinfo();
// if (rinfo->target_address() == Code::cast(check_code)->entry()) {
// cmp esp, <limit> ;; Not changed if (first) {
// nop first = false;
// nop } else {
// call <on-stack replacment> // The stack check code matches the pattern:
// test eax, <loop nesting depth> //
// ok: // cmp esp, <limit>
Address call_target_address = rinfo->pc(); // jae ok
ASSERT(*(call_target_address - 3) == 0x73 && // jae // call <stack guard>
*(call_target_address - 2) == 0x07 && // offset // test eax, <loop nesting depth>
*(call_target_address - 1) == 0xe8); // call // ok: ...
*(call_target_address - 3) = 0x90; // nop //
*(call_target_address - 2) = 0x90; // nop // We will patch away the branch so the code is:
rinfo->set_target_address(replacement_code->entry()); //
// cmp esp, <limit> ;; Not changed
// nop
// nop
// call <on-stack replacment>
// test eax, <loop nesting depth>
// ok:
Address call_target_address = rinfo->pc();
ASSERT(*(call_target_address - 3) == 0x73 && // jae
*(call_target_address - 2) == 0x07 && // offset
*(call_target_address - 1) == 0xe8); // call
*(call_target_address - 3) = 0x90; // nop
*(call_target_address - 2) = 0x90; // nop
rinfo->set_target_address(replacement_code->entry());
}
}
}
} }
void Deoptimizer::RevertStackCheckCode(RelocInfo* rinfo, Code* check_code) { void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
// Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to Code* check_code,
// restore the conditional branch. Code* replacement_code) {
Address call_target_address = rinfo->pc(); // Iterate the unoptimized code and revert all the patched stack checks.
ASSERT(*(call_target_address - 3) == 0x90 && // nop for (RelocIterator it(unoptimized_code, RelocInfo::kCodeTargetMask);
*(call_target_address - 2) == 0x90 && // nop !it.done();
*(call_target_address - 1) == 0xe8); // call it.next()) {
*(call_target_address - 3) = 0x73; // jae RelocInfo* rinfo = it.rinfo();
*(call_target_address - 2) = 0x07; // offset if (rinfo->target_address() == replacement_code->entry()) {
rinfo->set_target_address(check_code->entry()); // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
// restore the conditional branch.
Address call_target_address = rinfo->pc();
ASSERT(*(call_target_address - 3) == 0x90 && // nop
*(call_target_address - 2) == 0x90 && // nop
*(call_target_address - 1) == 0xe8); // call
*(call_target_address - 3) = 0x73; // jae
*(call_target_address - 2) = 0x07; // offset
rinfo->set_target_address(check_code->entry());
}
}
} }
......
...@@ -193,22 +193,9 @@ static void AttemptOnStackReplacement(JSFunction* function) { ...@@ -193,22 +193,9 @@ static void AttemptOnStackReplacement(JSFunction* function) {
if (maybe_check_code->ToObject(&check_code)) { if (maybe_check_code->ToObject(&check_code)) {
Code* replacement_code = Builtins::builtin(Builtins::OnStackReplacement); Code* replacement_code = Builtins::builtin(Builtins::OnStackReplacement);
Code* unoptimized_code = shared->code(); Code* unoptimized_code = shared->code();
// Iterate the unoptimized code and patch every stack check except at Deoptimizer::PatchStackCheckCode(unoptimized_code,
// the function entry. This code assumes the function entry stack Code::cast(check_code),
// check appears first i.e., is not deferred or otherwise reordered. replacement_code);
bool first = true;
for (RelocIterator it(unoptimized_code, RelocInfo::kCodeTargetMask);
!it.done();
it.next()) {
RelocInfo* rinfo = it.rinfo();
if (rinfo->target_address() == Code::cast(check_code)->entry()) {
if (first) {
first = false;
} else {
Deoptimizer::PatchStackCheckCode(rinfo, replacement_code);
}
}
}
} }
} }
......
...@@ -6944,15 +6944,9 @@ static MaybeObject* Runtime_CompileForOnStackReplacement(Arguments args) { ...@@ -6944,15 +6944,9 @@ static MaybeObject* Runtime_CompileForOnStackReplacement(Arguments args) {
Handle<Code> check_code = check_stub.GetCode(); Handle<Code> check_code = check_stub.GetCode();
Handle<Code> replacement_code( Handle<Code> replacement_code(
Builtins::builtin(Builtins::OnStackReplacement)); Builtins::builtin(Builtins::OnStackReplacement));
// Iterate the unoptimized code and revert all the patched stack checks. Deoptimizer::RevertStackCheckCode(*unoptimized,
for (RelocIterator it(*unoptimized, RelocInfo::kCodeTargetMask); *check_code,
!it.done(); *replacement_code);
it.next()) {
RelocInfo* rinfo = it.rinfo();
if (rinfo->target_address() == replacement_code->entry()) {
Deoptimizer::RevertStackCheckCode(rinfo, *check_code);
}
}
// Allow OSR only at nesting level zero again. // Allow OSR only at nesting level zero again.
unoptimized->set_allow_osr_at_loop_nesting_level(0); unoptimized->set_allow_osr_at_loop_nesting_level(0);
......
...@@ -46,13 +46,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { ...@@ -46,13 +46,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
} }
void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo, void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code) { Code* replacement_code) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void Deoptimizer::RevertStackCheckCode(RelocInfo* rinfo, Code* check_code) { void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
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