From: kmillikin@chromium.org Date: Sun, 20 Dec 2009 08:40:13 +0000 (+0000) Subject: Disallow garbage collection at another site in the LoadCallback ICs. X-Git-Tag: upstream/4.7.83~22783 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e1b13fc351aec1ede11f936aeba4602ae605574c;p=platform%2Fupstream%2Fv8.git Disallow garbage collection at another site in the LoadCallback ICs. MacroAssembler::PopHandleScope emits a runtime call (through a stub), which should not be allowed to perform a GC but return a failure instead. BUG=30790 TEST=none Review URL: http://codereview.chromium.org/504071 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3501 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index ac2895e..fb34925 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -1072,6 +1072,12 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { } +Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, + int num_arguments) { + return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); +} + + void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { // If the expected number of arguments of the runtime function is // constant, we check that the actual number of arguments match the @@ -1088,6 +1094,22 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { } +Object* MacroAssembler::TryCallRuntime(Runtime::Function* f, + int num_arguments) { + if (f->nargs >= 0 && f->nargs != num_arguments) { + IllegalOperation(num_arguments); + // Since we did not call the stub, there was no allocation failure. + // Return some non-failure object. + return Heap::undefined_value(); + } + + Runtime::FunctionId function_id = + static_cast(f->stub_id); + RuntimeStub stub(function_id, num_arguments); + return TryCallStub(&stub); +} + + void MacroAssembler::TailCallRuntime(const ExternalReference& ext, int num_arguments, int result_size) { @@ -1120,7 +1142,10 @@ void MacroAssembler::PushHandleScope(Register scratch) { } -void MacroAssembler::PopHandleScope(Register saved, Register scratch) { +Object* MacroAssembler::PopHandleScopeHelper(Register saved, + Register scratch, + bool gc_allowed) { + Object* result = NULL; ExternalReference extensions_address = ExternalReference::handle_scope_extensions_address(); Label write_back; @@ -1130,7 +1155,12 @@ void MacroAssembler::PopHandleScope(Register saved, Register scratch) { // Calling a runtime function messes with registers so we save and // restore any one we're asked not to change if (saved.is_valid()) push(saved); - CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); + if (gc_allowed) { + CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); + } else { + result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); + if (result->IsFailure()) return result; + } if (saved.is_valid()) pop(saved); bind(&write_back); @@ -1143,6 +1173,18 @@ void MacroAssembler::PopHandleScope(Register saved, Register scratch) { pop(scratch); shr(scratch, kSmiTagSize); mov(Operand::StaticVariable(extensions_address), scratch); + + return result; +} + + +void MacroAssembler::PopHandleScope(Register saved, Register scratch) { + PopHandleScopeHelper(saved, scratch, true); +} + + +Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { + return PopHandleScopeHelper(saved, scratch, false); } diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 50fe73a..a7c1754 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -319,9 +319,17 @@ class MacroAssembler: public Assembler { // Eventually this should be used for all C calls. void CallRuntime(Runtime::Function* f, int num_arguments); + // Call a runtime function, returning the RuntimeStub object called. + // Try to generate the stub code if necessary. Do not perform a GC + // but instead return a retry after GC failure. + Object* TryCallRuntime(Runtime::Function* f, int num_arguments); + // Convenience function: Same as above, but takes the fid instead. void CallRuntime(Runtime::FunctionId id, int num_arguments); + // Convenience function: Same as above, but takes the fid instead. + Object* TryCallRuntime(Runtime::FunctionId id, int num_arguments); + // Tail call of a runtime routine (jump). // Like JumpToRuntime, but also takes care of passing the number // of arguments. @@ -335,6 +343,10 @@ class MacroAssembler: public Assembler { // ensuring that saved register, it is not no_reg, is left unchanged. void PopHandleScope(Register saved, Register scratch); + // As PopHandleScope, but does not perform a GC. Instead, returns a + // retry after GC failure object if GC is necessary. + Object* TryPopHandleScope(Register saved, Register scratch); + // Jump to a runtime routine. void JumpToRuntime(const ExternalReference& ext); @@ -427,6 +439,13 @@ class MacroAssembler: public Assembler { Register scratch, AllocationFlags flags); void UpdateAllocationTopHelper(Register result_end, Register scratch); + + // Helper for PopHandleScope. Allowed to perform a GC and returns + // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and + // possibly returns a failure object indicating an allocation failure. + Object* PopHandleScopeHelper(Register saved, + Register scratch, + bool gc_allowed); }; diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 1dd5d95..a8ac6ab 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -802,9 +802,10 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, Address getter_address = v8::ToCData
(callback->getter()); ApiFunction fun(getter_address); ApiGetterEntryStub stub(callback_handle, &fun); - // Calling the stub may try to allocate (if the code is not already - // generated). Do not allow the call to perform a garbage - // collection but instead return the allocation failure object. + // Emitting a stub call may try to allocate (if the code is not + // already generated). Do not allow the assembler to perform a + // garbage collection but instead return the allocation failure + // object. Object* result = masm()->TryCallStub(&stub); if (result->IsFailure()) { *failure = Failure::cast(result); @@ -813,7 +814,14 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, // We need to avoid using eax since that now holds the result. Register tmp = other.is(eax) ? reg : other; - __ PopHandleScope(eax, tmp); + // Emitting PopHandleScope may try to allocate. Do not allow the + // assembler to perform a garbage collection but instead return a + // failure object. + result = masm()->TryPopHandleScope(eax, tmp); + if (result->IsFailure()) { + *failure = Failure::cast(result); + return false; + } __ LeaveInternalFrame(); __ ret(0);