Skip to content

Commit 321bed2

Browse files
Fixed problem where popping a handle scope after calling an accessor
would clobber the register holding the result. Review URL: http://codereview.chromium.org/377004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3237 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
1 parent 57c919e commit 321bed2

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

src/ia32/macro-assembler-ia32.cc

+5-1
Original file line numberDiff line numberDiff line change
@@ -973,14 +973,18 @@ void MacroAssembler::PushHandleScope(Register scratch) {
973973
}
974974

975975

976-
void MacroAssembler::PopHandleScope(Register scratch) {
976+
void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
977977
ExternalReference extensions_address =
978978
ExternalReference::handle_scope_extensions_address();
979979
Label write_back;
980980
mov(scratch, Operand::StaticVariable(extensions_address));
981981
cmp(Operand(scratch), Immediate(0));
982982
j(equal, &write_back);
983+
// Calling a runtime function messes with registers so we save and
984+
// restore any one we're asked not to change
985+
if (saved.is_valid()) push(saved);
983986
CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
987+
if (saved.is_valid()) pop(saved);
984988

985989
bind(&write_back);
986990
ExternalReference limit_address =

src/ia32/macro-assembler-ia32.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ class MacroAssembler: public Assembler {
272272
int result_size);
273273

274274
void PushHandleScope(Register scratch);
275-
void PopHandleScope(Register scratch);
275+
276+
// Pops a handle scope using the specified scratch register and
277+
// ensuring that saved register, it is not no_reg, is left unchanged.
278+
void PopHandleScope(Register saved, Register scratch);
276279

277280
// Jump to a runtime routine.
278281
void JumpToRuntime(const ExternalReference& ext);

src/ia32/stub-cache-ia32.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -804,8 +804,9 @@ void StubCompiler::GenerateLoadCallback(JSObject* object,
804804
ApiGetterEntryStub stub(callback_handle, &fun);
805805
__ CallStub(&stub);
806806

807+
// We need to avoid using eax since that now holds the result.
807808
Register tmp = other.is(eax) ? reg : other;
808-
__ PopHandleScope(tmp);
809+
__ PopHandleScope(eax, tmp);
809810
__ LeaveInternalFrame();
810811

811812
__ ret(0);

test/cctest/test-accessors.cc

+26
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,29 @@ THREADED_TEST(StackIteration) {
422422
" foo();"
423423
"}"))->Run();
424424
}
425+
426+
427+
static v8::Handle<Value> AllocateHandles(Local<String> name,
428+
const AccessorInfo& info) {
429+
for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
430+
v8::Local<v8::Value>::New(name);
431+
}
432+
return v8::Integer::New(100);
433+
}
434+
435+
436+
THREADED_TEST(HandleScopeSegment) {
437+
// Check that we can return values past popping of handle scope
438+
// segments.
439+
v8::HandleScope scope;
440+
v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
441+
obj->SetAccessor(v8_str("xxx"), AllocateHandles);
442+
LocalContext env;
443+
env->Global()->Set(v8_str("obj"), obj->NewInstance());
444+
v8::Handle<v8::Value> result = Script::Compile(String::New(
445+
"var result;"
446+
"for (var i = 0; i < 4; i++)"
447+
" result = obj.xxx;"
448+
"result;"))->Run();
449+
CHECK_EQ(100, result->Int32Value());
450+
}

0 commit comments

Comments
 (0)