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
parent d3e63a31
...@@ -1072,6 +1072,12 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { ...@@ -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) { void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
// If the expected number of arguments of the runtime function is // If the expected number of arguments of the runtime function is
// constant, we check that the actual number of arguments match the // constant, we check that the actual number of arguments match the
...@@ -1088,6 +1094,22 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { ...@@ -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<Runtime::FunctionId>(f->stub_id);
RuntimeStub stub(function_id, num_arguments);
return TryCallStub(&stub);
}
void MacroAssembler::TailCallRuntime(const ExternalReference& ext, void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
int num_arguments, int num_arguments,
int result_size) { int result_size) {
...@@ -1120,7 +1142,10 @@ void MacroAssembler::PushHandleScope(Register scratch) { ...@@ -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 extensions_address =
ExternalReference::handle_scope_extensions_address(); ExternalReference::handle_scope_extensions_address();
Label write_back; Label write_back;
...@@ -1130,7 +1155,12 @@ void MacroAssembler::PopHandleScope(Register saved, Register scratch) { ...@@ -1130,7 +1155,12 @@ void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
// Calling a runtime function messes with registers so we save and // Calling a runtime function messes with registers so we save and
// restore any one we're asked not to change // restore any one we're asked not to change
if (saved.is_valid()) push(saved); 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); if (saved.is_valid()) pop(saved);
bind(&write_back); bind(&write_back);
...@@ -1143,6 +1173,18 @@ void MacroAssembler::PopHandleScope(Register saved, Register scratch) { ...@@ -1143,6 +1173,18 @@ void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
pop(scratch); pop(scratch);
shr(scratch, kSmiTagSize); shr(scratch, kSmiTagSize);
mov(Operand::StaticVariable(extensions_address), scratch); 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);
} }
......
...@@ -319,9 +319,17 @@ class MacroAssembler: public Assembler { ...@@ -319,9 +319,17 @@ class MacroAssembler: public Assembler {
// Eventually this should be used for all C calls. // Eventually this should be used for all C calls.
void CallRuntime(Runtime::Function* f, int num_arguments); 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. // Convenience function: Same as above, but takes the fid instead.
void CallRuntime(Runtime::FunctionId id, int num_arguments); 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). // Tail call of a runtime routine (jump).
// Like JumpToRuntime, but also takes care of passing the number // Like JumpToRuntime, but also takes care of passing the number
// of arguments. // of arguments.
...@@ -335,6 +343,10 @@ class MacroAssembler: public Assembler { ...@@ -335,6 +343,10 @@ class MacroAssembler: public Assembler {
// ensuring that saved register, it is not no_reg, is left unchanged. // ensuring that saved register, it is not no_reg, is left unchanged.
void PopHandleScope(Register saved, Register scratch); 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. // Jump to a runtime routine.
void JumpToRuntime(const ExternalReference& ext); void JumpToRuntime(const ExternalReference& ext);
...@@ -427,6 +439,13 @@ class MacroAssembler: public Assembler { ...@@ -427,6 +439,13 @@ class MacroAssembler: public Assembler {
Register scratch, Register scratch,
AllocationFlags flags); AllocationFlags flags);
void UpdateAllocationTopHelper(Register result_end, Register scratch); 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);
}; };
......
...@@ -802,9 +802,10 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, ...@@ -802,9 +802,10 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
Address getter_address = v8::ToCData<Address>(callback->getter()); Address getter_address = v8::ToCData<Address>(callback->getter());
ApiFunction fun(getter_address); ApiFunction fun(getter_address);
ApiGetterEntryStub stub(callback_handle, &fun); ApiGetterEntryStub stub(callback_handle, &fun);
// Calling the stub may try to allocate (if the code is not already // Emitting a stub call may try to allocate (if the code is not
// generated). Do not allow the call to perform a garbage // already generated). Do not allow the assembler to perform a
// collection but instead return the allocation failure object. // garbage collection but instead return the allocation failure
// object.
Object* result = masm()->TryCallStub(&stub); Object* result = masm()->TryCallStub(&stub);
if (result->IsFailure()) { if (result->IsFailure()) {
*failure = Failure::cast(result); *failure = Failure::cast(result);
...@@ -813,7 +814,14 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, ...@@ -813,7 +814,14 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
// We need to avoid using eax since that now holds the result. // We need to avoid using eax since that now holds the result.
Register tmp = other.is(eax) ? reg : other; 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(); __ LeaveInternalFrame();
__ ret(0); __ ret(0);
......
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