Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(587)

Unified Diff: src/builtins/ia32/builtins-ia32.cc

Issue 2841913003: [WIP] Initial CallFunctionCallback builtin.
Patch Set: Fix wrong register for arm64. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins/builtins-definitions.h ('k') | src/builtins/mips/builtins-mips.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/ia32/builtins-ia32.cc
diff --git a/src/builtins/ia32/builtins-ia32.cc b/src/builtins/ia32/builtins-ia32.cc
index c907fa8dfe9e941688f912f5bab84e3313ed24fb..9390e312492ff89e8132ab5046de949d9325fb6c 100644
--- a/src/builtins/ia32/builtins-ia32.cc
+++ b/src/builtins/ia32/builtins-ia32.cc
@@ -4,6 +4,7 @@
#if V8_TARGET_ARCH_IA32
+#include "src/api-arguments.h"
#include "src/code-factory.h"
#include "src/codegen.h"
#include "src/deoptimizer.h"
@@ -2875,6 +2876,167 @@ void Builtins::Generate_CallWithSpread(MacroAssembler* masm) {
RelocInfo::CODE_TARGET);
}
+namespace {
+
+// Prepares stack to put arguments (aligns and so on). Reserves
+// space for return value if needed (assumes the return value is a handle).
+// Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
+// etc. Saves context (esi). If space was reserved for return value then
+// stores the pointer to the reserved slot into esi.
+void PrepareCallApiFunction(MacroAssembler* masm, int argc) {
+ __ EnterApiExitFrame(argc);
+ if (__ emit_debug_code()) {
+ __ mov(esi, Immediate(bit_cast<int32_t>(kZapValue)));
+ }
+}
+
+// Generates an Operand for saving parameters after PrepareCallApiFunction.
+Operand ApiParameterOperand(int index) {
+ return MemOperand(esp, index * kPointerSize);
+}
+
+} // namespace
+
+// static
+void Builtins::Generate_CallFunctionCallback(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- eax : the number of arguments (not incl. the receiver)
+ // -- edx : api function address
+ // -- esp[0] : return address
+ // -- esp[4] : holder
+ // -- esp[8] : isolate
+ // -- esp[12] : return value default
+ // -- esp[16] : return value
+ // -- esp[20] : call data
+ // -- esp[24] : target
+ // -- esp[28] : context save
+ // -- esp[32] : new.target
+ // -- esp[36] : last argument
+ // -- esp[32 + argc * 4] : first argument
+ // -- esp[36 + argc * 4] : receiver
+ // -----------------------------------
+ typedef FunctionCallbackArguments FCA;
+
+ STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+ STATIC_ASSERT(FCA::kContextSaveIndex == 6);
+ STATIC_ASSERT(FCA::kCalleeIndex == 5);
+ STATIC_ASSERT(FCA::kDataIndex == 4);
+ STATIC_ASSERT(FCA::kReturnValueOffset == 3);
+ STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
+ STATIC_ASSERT(FCA::kIsolateIndex == 1);
+ STATIC_ASSERT(FCA::kHolderIndex == 0);
+ STATIC_ASSERT(FCA::kArgsLength == 8);
+
+ // Compute the pointer to the implicit args on the stack.
+ __ lea(ebx, MemOperand(esp, kPCOnStackSize));
+
+ // API function gets reference to the v8::Arguments. If CPU profiler
+ // is enabled wrapper function will be called and we need to pass
+ // address of the callback as additional parameter, always allocate
+ // space for it.
+ const int kApiArgc = 1 + 1;
+
+ // Allocate the v8::FunctionCallbackInfo structure in the arguments' space
+ // since it's not controlled by the GC.
+ const int kApiStackSpace = 3;
+ PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace);
+ // Initialize FunctionCallbackInfo::implicit_args_.
+ __ mov(ApiParameterOperand(2), ebx);
+ // Initialize FunctionCallbackInfo::values_.
+ __ lea(ebx, MemOperand(ebx, eax, times_pointer_size,
+ (FCA::kArgsLength - 1) * kPointerSize));
+ __ mov(ApiParameterOperand(3), ebx);
+ // Initialize FunctionCallbackInfo::length_.
+ __ mov(ApiParameterOperand(4), eax);
+
+ // Load first argument with pointer to FunctionCallbackInfo.
+ __ lea(ebx, ApiParameterOperand(2));
+ __ mov(ApiParameterOperand(0), ebx);
+
+ ExternalReference const next_address =
+ ExternalReference::handle_scope_next_address(masm->isolate());
+ ExternalReference const limit_address =
+ ExternalReference::handle_scope_limit_address(masm->isolate());
+ ExternalReference const level_address =
+ ExternalReference::handle_scope_level_address(masm->isolate());
+
+ // 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));
+
+ // Check if profiling is active, and if so call the function indirectly
+ // via the invoke_function_callback helper.
+ Label call_indirect, done_call;
+ __ cmpb(Operand::StaticVariable(
+ ExternalReference::is_profiling_address(masm->isolate())),
+ Immediate(0));
+ __ j(not_zero, &call_indirect, Label::kNear);
+ {
+ // Call the API function directly.
+ __ call(edx);
+ }
+ __ jmp(&done_call, Label::kNear);
+ __ bind(&call_indirect);
+ {
+ // Call the API function indirectly when profiling is on.
+ __ mov(ApiParameterOperand(1), edx);
+ __ mov(eax, Immediate(ExternalReference::invoke_function_callback(
+ masm->isolate())));
+ __ call(eax);
+ }
+ __ bind(&done_call);
+
+ // No more valid handles (the result handle was the last one). Restore
+ // previous handle scope.
+ Label delete_allocated_handles;
+ __ mov(Operand::StaticVariable(next_address), ebx);
+ __ sub(Operand::StaticVariable(level_address), Immediate(1));
+ __ cmp(edi, Operand::StaticVariable(limit_address));
+ __ j(not_equal, &delete_allocated_handles);
+
+ // Leave the API exit frame.
+ Label leave_exit_frame;
+ __ bind(&leave_exit_frame);
+ __ mov(eax, MemOperand(ebp, (2 + FCA::kReturnValueOffset) * kPointerSize));
+ __ mov(esi, MemOperand(ebp, (2 + FCA::kContextSaveIndex) * kPointerSize));
+ __ mov(ebx, ApiParameterOperand(4));
+ __ LeaveApiExitFrame(false);
+
+ // Check if the function scheduled an exception.
+ Label promote_scheduled_exception;
+ __ cmp(Operand::StaticVariable(
+ ExternalReference::scheduled_exception_address(masm->isolate())),
+ Immediate(masm->isolate()->factory()->the_hole_value()));
+ __ j(not_equal, &promote_scheduled_exception);
+
+ // Check if the function returned a valid JavaScript value.
+ __ AssertApiCallResult(eax);
+
+ // Drop the arguments and return.
+ __ PopReturnAddressTo(ecx);
+ __ lea(esp, MemOperand(esp, ebx, times_pointer_size,
+ (FCA::kArgsLength + 1) * kPointerSize));
+ __ PushReturnAddressFrom(ecx);
+ __ Ret();
+
+ // Re-throw by promoting a scheduled exception.
+ __ bind(&promote_scheduled_exception);
+ __ TailCallRuntime(Runtime::kPromoteScheduledException);
+
+ // HandleScope limit has changed. Delete allocated extensions.
+ __ bind(&delete_allocated_handles);
+ {
+ __ mov(Operand::StaticVariable(limit_address), edi);
+ __ mov(Operand(esp, 0),
+ Immediate(ExternalReference::isolate_address(masm->isolate())));
+ __ mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions(
+ masm->isolate())));
+ __ call(eax);
+ }
+ __ jmp(&leave_exit_frame);
+}
+
// static
void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
// ----------- S t a t e -------------
« no previous file with comments | « src/builtins/builtins-definitions.h ('k') | src/builtins/mips/builtins-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698