| Index: src/ia32/macro-assembler-ia32.cc
|
| ===================================================================
|
| --- src/ia32/macro-assembler-ia32.cc (revision 5685)
|
| +++ src/ia32/macro-assembler-ia32.cc (working copy)
|
| @@ -1075,66 +1075,116 @@
|
| }
|
|
|
|
|
| -void MacroAssembler::PushHandleScope(Register scratch) {
|
| - // Push the number of extensions, smi-tagged so the gc will ignore it.
|
| - ExternalReference extensions_address =
|
| - ExternalReference::handle_scope_extensions_address();
|
| - mov(scratch, Operand::StaticVariable(extensions_address));
|
| - SmiTag(scratch);
|
| - push(scratch);
|
| - mov(Operand::StaticVariable(extensions_address), Immediate(0));
|
| - // Push next and limit pointers which will be wordsize aligned and
|
| - // hence automatically smi tagged.
|
| - ExternalReference next_address =
|
| - ExternalReference::handle_scope_next_address();
|
| - push(Operand::StaticVariable(next_address));
|
| - ExternalReference limit_address =
|
| - ExternalReference::handle_scope_limit_address();
|
| - push(Operand::StaticVariable(limit_address));
|
| +// If true, a Handle<T> passed by value is passed and returned by
|
| +// using the location_ field directly. If false, it is passed and
|
| +// returned as a pointer to a handle.
|
| +#ifdef USING_BSD_ABI
|
| +static const bool kPassHandlesDirectly = true;
|
| +#else
|
| +static const bool kPassHandlesDirectly = false;
|
| +#endif
|
| +
|
| +
|
| +Operand ApiParameterOperand(int index) {
|
| + return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize);
|
| }
|
|
|
|
|
| -Object* MacroAssembler::PopHandleScopeHelper(Register saved,
|
| - Register scratch,
|
| - bool gc_allowed) {
|
| - Object* result = NULL;
|
| - ExternalReference extensions_address =
|
| - ExternalReference::handle_scope_extensions_address();
|
| - Label write_back;
|
| - mov(scratch, Operand::StaticVariable(extensions_address));
|
| - cmp(Operand(scratch), Immediate(0));
|
| - j(equal, &write_back);
|
| - push(saved);
|
| - if (gc_allowed) {
|
| - CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
|
| +void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) {
|
| + if (kPassHandlesDirectly) {
|
| + EnterApiExitFrame(stack_space, argc);
|
| + // When handles as passed directly we don't have to allocate extra
|
| + // space for and pass an out parameter.
|
| } else {
|
| - result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
|
| - if (result->IsFailure()) return result;
|
| + // We allocate two additional slots: return value and pointer to it.
|
| + EnterApiExitFrame(stack_space, argc + 2);
|
| }
|
| - pop(saved);
|
| +}
|
|
|
| - bind(&write_back);
|
| +
|
| +void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) {
|
| + if (!kPassHandlesDirectly) {
|
| + // The argument slots are filled as follows:
|
| + //
|
| + // n + 1: output cell
|
| + // n: arg n
|
| + // ...
|
| + // 1: arg1
|
| + // 0: pointer to the output cell
|
| + //
|
| + // Note that this is one more "argument" than the function expects
|
| + // so the out cell will have to be popped explicitly after returning
|
| + // from the function. The out cell contains Handle.
|
| + lea(eax, Operand(esp, (argc + 1) * kPointerSize)); // pointer to out cell.
|
| + mov(Operand(esp, 0 * kPointerSize), eax); // output.
|
| + mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell.
|
| + }
|
| +
|
| + ExternalReference next_address =
|
| + ExternalReference::handle_scope_next_address();
|
| ExternalReference limit_address =
|
| - ExternalReference::handle_scope_limit_address();
|
| - pop(Operand::StaticVariable(limit_address));
|
| - ExternalReference next_address =
|
| - ExternalReference::handle_scope_next_address();
|
| - pop(Operand::StaticVariable(next_address));
|
| - pop(scratch);
|
| - SmiUntag(scratch);
|
| - mov(Operand::StaticVariable(extensions_address), scratch);
|
| + ExternalReference::handle_scope_limit_address();
|
| + ExternalReference level_address =
|
| + ExternalReference::handle_scope_level_address();
|
|
|
| - return result;
|
| -}
|
| + // Allocate HandleScope in callee-save registers.
|
| + mov(ebx, Operand::StaticVariable(next_address));
|
| + mov(edi, Operand::StaticVariable(limit_address));
|
| + add(Operand::StaticVariable(level_address), Immediate(1));
|
|
|
| + // Call the api function!
|
| + call(function->address(), RelocInfo::RUNTIME_ENTRY);
|
|
|
| -void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
|
| - PopHandleScopeHelper(saved, scratch, true);
|
| -}
|
| + if (!kPassHandlesDirectly) {
|
| + // The returned value is a pointer to the handle holding the result.
|
| + // Dereference this to get to the location.
|
| + mov(eax, Operand(eax, 0));
|
| + }
|
|
|
| + Label empty_handle;
|
| + Label prologue;
|
| + Label promote_scheduled_exception;
|
| + Label delete_allocated_handles;
|
| + Label leave_exit_frame;
|
|
|
| -Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
|
| - return PopHandleScopeHelper(saved, scratch, false);
|
| + // Check if the result handle holds 0.
|
| + test(eax, Operand(eax));
|
| + j(zero, &empty_handle, not_taken);
|
| + // It was non-zero. Dereference to get the result value.
|
| + mov(eax, Operand(eax, 0));
|
| + bind(&prologue);
|
| + // No more valid handles (the result handle was the last one). Restore
|
| + // previous handle scope.
|
| + mov(Operand::StaticVariable(next_address), ebx);
|
| + sub(Operand::StaticVariable(level_address), Immediate(1));
|
| + Assert(above_equal, "Invalid HandleScope level");
|
| + cmp(edi, Operand::StaticVariable(limit_address));
|
| + j(not_equal, &delete_allocated_handles, not_taken);
|
| + bind(&leave_exit_frame);
|
| +
|
| + // Check if the function scheduled an exception.
|
| + ExternalReference scheduled_exception_address =
|
| + ExternalReference::scheduled_exception_address();
|
| + cmp(Operand::StaticVariable(scheduled_exception_address),
|
| + Immediate(Factory::the_hole_value()));
|
| + j(not_equal, &promote_scheduled_exception, not_taken);
|
| + LeaveExitFrame();
|
| + ret(0);
|
| + bind(&promote_scheduled_exception);
|
| + TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
|
| + bind(&empty_handle);
|
| + // It was zero; the result is undefined.
|
| + mov(eax, Factory::undefined_value());
|
| + jmp(&prologue);
|
| +
|
| + // HandleScope limit has changed. Delete allocated extensions.
|
| + bind(&delete_allocated_handles);
|
| + mov(Operand::StaticVariable(limit_address), edi);
|
| + mov(edi, eax);
|
| + mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions()));
|
| + call(Operand(eax));
|
| + mov(eax, edi);
|
| + jmp(&leave_exit_frame);
|
| }
|
|
|
|
|
|
|