Notify CPU profiler when calling native getters
This change modifies code produced by BaseLoadStubCompiler::GenerateLoadCallback so that instead of calling AccessorGetter direcly it calls InvokeAccessorGetter which changes VM state and calls the actual callback. This way CPU profiler knows which external callback is being executed in this case. BUG=244580 R=dcarney@chromium.org, loislo@chromium.org, svenpanne@chromium.org Review URL: https://codereview.chromium.org/16286016 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15116 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
6e0aa78a40
commit
1a3c3cee9d
51
src/api.cc
51
src/api.cc
@ -8005,4 +8005,55 @@ void DeferredHandles::Iterate(ObjectVisitor* v) {
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> InvokeAccessorGetter(
|
||||
v8::Local<v8::String> property,
|
||||
const v8::AccessorInfo& info,
|
||||
v8::AccessorGetter getter) {
|
||||
Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
|
||||
Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
|
||||
getter));
|
||||
// Leaving JavaScript.
|
||||
VMState<EXTERNAL> state(isolate);
|
||||
ExternalCallbackScope call_scope(isolate, getter_address);
|
||||
return getter(property, info);
|
||||
}
|
||||
|
||||
|
||||
void InvokeAccessorGetterCallback(
|
||||
v8::Local<v8::String> property,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info,
|
||||
v8::AccessorGetterCallback getter) {
|
||||
// Leaving JavaScript.
|
||||
Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
|
||||
Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
|
||||
getter));
|
||||
VMState<EXTERNAL> state(isolate);
|
||||
ExternalCallbackScope call_scope(isolate, getter_address);
|
||||
return getter(property, info);
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> InvokeInvocationCallback(
|
||||
const v8::Arguments& args,
|
||||
v8::InvocationCallback callback) {
|
||||
Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate());
|
||||
Address callback_address =
|
||||
reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
|
||||
VMState<EXTERNAL> state(isolate);
|
||||
ExternalCallbackScope call_scope(isolate, callback_address);
|
||||
return callback(args);
|
||||
}
|
||||
|
||||
|
||||
void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
|
||||
v8::FunctionCallback callback) {
|
||||
Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
|
||||
Address callback_address =
|
||||
reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
|
||||
VMState<EXTERNAL> state(isolate);
|
||||
ExternalCallbackScope call_scope(isolate, callback_address);
|
||||
return callback(info);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
18
src/api.h
18
src/api.h
@ -680,6 +680,24 @@ void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
|
||||
}
|
||||
|
||||
|
||||
// Interceptor functions called from generated inline caches to notify
|
||||
// CPU profiler that external callbacks are invoked.
|
||||
v8::Handle<v8::Value> InvokeAccessorGetter(
|
||||
v8::Local<v8::String> property,
|
||||
const v8::AccessorInfo& info,
|
||||
v8::AccessorGetter getter);
|
||||
|
||||
|
||||
void InvokeAccessorGetterCallback(
|
||||
v8::Local<v8::String> property,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info,
|
||||
v8::AccessorGetterCallback getter);
|
||||
|
||||
v8::Handle<v8::Value> InvokeInvocationCallback(const v8::Arguments& args,
|
||||
v8::InvocationCallback callback);
|
||||
void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
|
||||
v8::FunctionCallback callback);
|
||||
|
||||
class Testing {
|
||||
public:
|
||||
static v8::Testing::StressType stress_type() { return stress_type_; }
|
||||
|
@ -6481,13 +6481,6 @@ void DirectCEntryStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
||||
ExternalReference function) {
|
||||
__ mov(r2, Operand(function));
|
||||
GenerateCall(masm, r2);
|
||||
}
|
||||
|
||||
|
||||
void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
||||
Register target) {
|
||||
intptr_t code =
|
||||
|
@ -585,7 +585,6 @@ class DirectCEntryStub: public PlatformCodeStub {
|
||||
public:
|
||||
DirectCEntryStub() {}
|
||||
void Generate(MacroAssembler* masm);
|
||||
void GenerateCall(MacroAssembler* masm, ExternalReference function);
|
||||
void GenerateCall(MacroAssembler* masm, Register target);
|
||||
|
||||
private:
|
||||
|
@ -2244,6 +2244,9 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
|
||||
|
||||
|
||||
void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
|
||||
Address function_address,
|
||||
ExternalReference thunk_ref,
|
||||
Register thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset) {
|
||||
@ -2274,11 +2277,31 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
|
||||
PopSafepointRegisters();
|
||||
}
|
||||
|
||||
ASSERT(!thunk_last_arg.is(r3));
|
||||
Label profiler_disabled;
|
||||
Label end_profiler_check;
|
||||
bool* is_profiling_flag =
|
||||
isolate()->cpu_profiler()->is_profiling_address();
|
||||
STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
|
||||
mov(r3, Operand(reinterpret_cast<int32_t>(is_profiling_flag)));
|
||||
ldrb(r3, MemOperand(r3, 0));
|
||||
cmp(r3, Operand(0));
|
||||
b(eq, &profiler_disabled);
|
||||
|
||||
// Additional parameter is the address of the actual callback.
|
||||
mov(thunk_last_arg, Operand(reinterpret_cast<int32_t>(function_address)));
|
||||
mov(r3, Operand(thunk_ref));
|
||||
jmp(&end_profiler_check);
|
||||
|
||||
bind(&profiler_disabled);
|
||||
mov(r3, Operand(function));
|
||||
bind(&end_profiler_check);
|
||||
|
||||
// Native call returns to the DirectCEntry stub which redirects to the
|
||||
// return address pushed on stack (could have moved after GC).
|
||||
// DirectCEntry stub itself is generated early and never moves.
|
||||
DirectCEntryStub stub;
|
||||
stub.GenerateCall(this, function);
|
||||
stub.GenerateCall(this, r3);
|
||||
|
||||
if (FLAG_log_timer_events) {
|
||||
FrameScope frame(this, StackFrame::MANUAL);
|
||||
|
@ -1085,6 +1085,9 @@ class MacroAssembler: public Assembler {
|
||||
// - space to be unwound on exit (includes the call JS arguments space and
|
||||
// the additional space allocated for the fast call).
|
||||
void CallApiFunctionAndReturn(ExternalReference function,
|
||||
Address function_address,
|
||||
ExternalReference thunk_ref,
|
||||
Register thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset_from_fp);
|
||||
|
@ -830,7 +830,10 @@ class Redirection {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
Redirection* current = isolate->simulator_redirection();
|
||||
for (; current != NULL; current = current->next_) {
|
||||
if (current->external_function_ == external_function) return current;
|
||||
if (current->external_function_ == external_function) {
|
||||
ASSERT_EQ(current->type(), type);
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return new Redirection(external_function, type);
|
||||
}
|
||||
@ -1629,12 +1632,19 @@ typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
|
||||
// (refer to InvocationCallback in v8.h).
|
||||
typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
|
||||
typedef void (*SimulatorRuntimeDirectApiCallNew)(int32_t arg0);
|
||||
typedef v8::Handle<v8::Value> (*SimulatorRuntimeProfilingApiCall)(
|
||||
int32_t arg0, int32_t arg1);
|
||||
typedef void (*SimulatorRuntimeProfilingApiCallNew)(int32_t arg0, int32_t arg1);
|
||||
|
||||
// This signature supports direct call to accessor getter callback.
|
||||
typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
|
||||
int32_t arg1);
|
||||
typedef void (*SimulatorRuntimeDirectGetterCallNew)(int32_t arg0,
|
||||
int32_t arg1);
|
||||
typedef v8::Handle<v8::Value> (*SimulatorRuntimeProfilingGetterCall)(
|
||||
int32_t arg0, int32_t arg1, int32_t arg2);
|
||||
typedef void (*SimulatorRuntimeProfilingGetterCallNew)(
|
||||
int32_t arg0, int32_t arg1, int32_t arg2);
|
||||
|
||||
// Software interrupt instructions are used by the simulator to call into the
|
||||
// C-based V8 runtime.
|
||||
@ -1798,6 +1808,31 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
||||
reinterpret_cast<SimulatorRuntimeDirectApiCallNew>(external);
|
||||
target(arg0);
|
||||
}
|
||||
} else if (
|
||||
redirection->type() == ExternalReference::PROFILING_API_CALL ||
|
||||
redirection->type() == ExternalReference::PROFILING_API_CALL_NEW) {
|
||||
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
||||
PrintF("Call to host function at %p args %08x %08x",
|
||||
reinterpret_cast<void*>(external), arg0, arg1);
|
||||
if (!stack_aligned) {
|
||||
PrintF(" with unaligned stack %08x\n", get_register(sp));
|
||||
}
|
||||
PrintF("\n");
|
||||
}
|
||||
CHECK(stack_aligned);
|
||||
if (redirection->type() == ExternalReference::PROFILING_API_CALL) {
|
||||
SimulatorRuntimeProfilingApiCall target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
|
||||
v8::Handle<v8::Value> result = target(arg0, arg1);
|
||||
if (::v8::internal::FLAG_trace_sim) {
|
||||
PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
|
||||
}
|
||||
set_register(r0, reinterpret_cast<int32_t>(*result));
|
||||
} else {
|
||||
SimulatorRuntimeProfilingApiCallNew target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingApiCallNew>(external);
|
||||
target(arg0, arg1);
|
||||
}
|
||||
} else if (
|
||||
redirection->type() == ExternalReference::DIRECT_GETTER_CALL ||
|
||||
redirection->type() == ExternalReference::DIRECT_GETTER_CALL_NEW) {
|
||||
@ -1823,6 +1858,32 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
||||
reinterpret_cast<SimulatorRuntimeDirectGetterCallNew>(external);
|
||||
target(arg0, arg1);
|
||||
}
|
||||
} else if (
|
||||
redirection->type() == ExternalReference::PROFILING_GETTER_CALL ||
|
||||
redirection->type() == ExternalReference::PROFILING_GETTER_CALL_NEW) {
|
||||
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
||||
PrintF("Call to host function at %p args %08x %08x %08x",
|
||||
reinterpret_cast<void*>(external), arg0, arg1, arg2);
|
||||
if (!stack_aligned) {
|
||||
PrintF(" with unaligned stack %08x\n", get_register(sp));
|
||||
}
|
||||
PrintF("\n");
|
||||
}
|
||||
CHECK(stack_aligned);
|
||||
if (redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
|
||||
SimulatorRuntimeProfilingGetterCall target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
|
||||
v8::Handle<v8::Value> result = target(arg0, arg1, arg2);
|
||||
if (::v8::internal::FLAG_trace_sim) {
|
||||
PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
|
||||
}
|
||||
set_register(r0, reinterpret_cast<int32_t>(*result));
|
||||
} else {
|
||||
SimulatorRuntimeProfilingGetterCallNew target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingGetterCallNew>(
|
||||
external);
|
||||
target(arg0, arg1, arg2);
|
||||
}
|
||||
} else {
|
||||
// builtin call.
|
||||
ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
|
||||
@ -1830,7 +1891,7 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
||||
reinterpret_cast<SimulatorRuntimeCall>(external);
|
||||
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
||||
PrintF(
|
||||
"Call to host function at %p"
|
||||
"Call to host function at %p "
|
||||
"args %08x, %08x, %08x, %08x, %08x, %08x",
|
||||
FUNCTION_ADDR(target),
|
||||
arg0,
|
||||
|
@ -956,8 +956,22 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
|
||||
ExternalReference ref = ExternalReference(&fun,
|
||||
type,
|
||||
masm->isolate());
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeInvocationCallback)
|
||||
: FUNCTION_ADDR(&InvokeFunctionCallback);
|
||||
ExternalReference::Type thunk_type =
|
||||
returns_handle ?
|
||||
ExternalReference::PROFILING_API_CALL :
|
||||
ExternalReference::PROFILING_API_CALL_NEW;
|
||||
ApiFunction thunk_fun(thunk_address);
|
||||
ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
|
||||
masm->isolate());
|
||||
|
||||
AllowExternalCallThatCantCauseGC scope(masm);
|
||||
__ CallApiFunctionAndReturn(ref,
|
||||
function_address,
|
||||
thunk_ref,
|
||||
r1,
|
||||
kStackUnwindSpace,
|
||||
returns_handle,
|
||||
kFastApiCallArguments + 1);
|
||||
@ -1454,14 +1468,28 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
|
||||
Address getter_address = v8::ToCData<Address>(callback->getter());
|
||||
bool returns_handle =
|
||||
!CallbackTable::ReturnsVoid(isolate(), getter_address);
|
||||
|
||||
ApiFunction fun(getter_address);
|
||||
ExternalReference::Type type =
|
||||
returns_handle ?
|
||||
ExternalReference::DIRECT_GETTER_CALL :
|
||||
ExternalReference::DIRECT_GETTER_CALL_NEW;
|
||||
|
||||
ExternalReference ref = ExternalReference(&fun, type, isolate());
|
||||
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeAccessorGetter)
|
||||
: FUNCTION_ADDR(&InvokeAccessorGetterCallback);
|
||||
ExternalReference::Type thunk_type =
|
||||
returns_handle ?
|
||||
ExternalReference::PROFILING_GETTER_CALL :
|
||||
ExternalReference::PROFILING_GETTER_CALL_NEW;
|
||||
ApiFunction thunk_fun(thunk_address);
|
||||
ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
|
||||
isolate());
|
||||
__ CallApiFunctionAndReturn(ref,
|
||||
getter_address,
|
||||
thunk_ref,
|
||||
r2,
|
||||
kStackUnwindSpace,
|
||||
returns_handle,
|
||||
5);
|
||||
|
@ -647,17 +647,35 @@ class ExternalReference BASE_EMBEDDED {
|
||||
// Handle<Value> f(v8::Arguments&)
|
||||
DIRECT_API_CALL,
|
||||
|
||||
// Call to invocation callback via InvokeInvocationCallback.
|
||||
// Handle<Value> f(v8::Arguments&, v8::InvocationCallback)
|
||||
PROFILING_API_CALL,
|
||||
|
||||
// Direct call to API function callback.
|
||||
// void f(v8::Arguments&)
|
||||
DIRECT_API_CALL_NEW,
|
||||
|
||||
// Call to function callback via InvokeFunctionCallback.
|
||||
// void f(v8::Arguments&, v8::FunctionCallback)
|
||||
PROFILING_API_CALL_NEW,
|
||||
|
||||
// Direct call to accessor getter callback.
|
||||
// Handle<value> f(Local<String> property, AccessorInfo& info)
|
||||
DIRECT_GETTER_CALL,
|
||||
|
||||
// Call to accessor getter callback via InvokeAccessorGetter.
|
||||
// Handle<value> f(Local<String> property, AccessorInfo& info,
|
||||
// AccessorGetter getter)
|
||||
PROFILING_GETTER_CALL,
|
||||
|
||||
// Direct call to accessor getter callback.
|
||||
// void f(Local<String> property, AccessorInfo& info)
|
||||
DIRECT_GETTER_CALL_NEW
|
||||
DIRECT_GETTER_CALL_NEW,
|
||||
|
||||
// Call to accessor getter callback via InvokeAccessorGetterCallback.
|
||||
// void f(Local<String> property, AccessorInfo& info,
|
||||
// AccessorGetterCallback callback)
|
||||
PROFILING_GETTER_CALL_NEW
|
||||
};
|
||||
|
||||
static void SetUp();
|
||||
|
@ -248,6 +248,9 @@ class CpuProfiler {
|
||||
void SharedFunctionInfoMoveEvent(Address from, Address to);
|
||||
|
||||
INLINE(bool is_profiling() const) { return is_profiling_; }
|
||||
bool* is_profiling_address() {
|
||||
return &is_profiling_;
|
||||
}
|
||||
|
||||
private:
|
||||
void StartProcessorIfNotStarted();
|
||||
|
@ -1973,6 +1973,8 @@ void MacroAssembler::PrepareCallApiFunction(int argc, bool returns_handle) {
|
||||
|
||||
|
||||
void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
|
||||
Address thunk_address,
|
||||
Operand thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset) {
|
||||
@ -1998,8 +2000,26 @@ void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
|
||||
PopSafepointRegisters();
|
||||
}
|
||||
|
||||
|
||||
Label profiler_disabled;
|
||||
Label end_profiler_check;
|
||||
bool* is_profiling_flag =
|
||||
isolate()->cpu_profiler()->is_profiling_address();
|
||||
STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
|
||||
mov(eax, Immediate(reinterpret_cast<Address>(is_profiling_flag)));
|
||||
cmpb(Operand(eax, 0), 0);
|
||||
j(zero, &profiler_disabled);
|
||||
|
||||
// Additional parameter is the address of the actual getter function.
|
||||
mov(thunk_last_arg, Immediate(function_address));
|
||||
// Call the api function.
|
||||
call(thunk_address, RelocInfo::RUNTIME_ENTRY);
|
||||
jmp(&end_profiler_check);
|
||||
|
||||
bind(&profiler_disabled);
|
||||
// Call the api function.
|
||||
call(function_address, RelocInfo::RUNTIME_ENTRY);
|
||||
bind(&end_profiler_check);
|
||||
|
||||
if (FLAG_log_timer_events) {
|
||||
FrameScope frame(this, StackFrame::MANUAL);
|
||||
|
@ -784,6 +784,8 @@ class MacroAssembler: public Assembler {
|
||||
// caller-save registers. Restores context. On return removes
|
||||
// stack_space * kPointerSize (GCed).
|
||||
void CallApiFunctionAndReturn(Address function_address,
|
||||
Address thunk_address,
|
||||
Operand thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset_from_ebp);
|
||||
|
@ -503,7 +503,12 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
||||
STATIC_ASSERT(kFastApiCallArguments == 6);
|
||||
__ lea(eax, Operand(esp, kFastApiCallArguments * kPointerSize));
|
||||
|
||||
const int kApiArgc = 1; // API function gets reference to the v8::Arguments.
|
||||
|
||||
// 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::Arguments structure in the arguments' space since
|
||||
// it's not controlled by GC.
|
||||
@ -517,20 +522,26 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
||||
__ PrepareCallApiFunction(kApiArgc + kApiStackSpace, returns_handle);
|
||||
|
||||
// v8::Arguments::implicit_args_.
|
||||
__ mov(ApiParameterOperand(1, returns_handle), eax);
|
||||
__ mov(ApiParameterOperand(2, returns_handle), eax);
|
||||
__ add(eax, Immediate(argc * kPointerSize));
|
||||
// v8::Arguments::values_.
|
||||
__ mov(ApiParameterOperand(2, returns_handle), eax);
|
||||
__ mov(ApiParameterOperand(3, returns_handle), eax);
|
||||
// v8::Arguments::length_.
|
||||
__ Set(ApiParameterOperand(3, returns_handle), Immediate(argc));
|
||||
__ Set(ApiParameterOperand(4, returns_handle), Immediate(argc));
|
||||
// v8::Arguments::is_construct_call_.
|
||||
__ Set(ApiParameterOperand(4, returns_handle), Immediate(0));
|
||||
__ Set(ApiParameterOperand(5, returns_handle), Immediate(0));
|
||||
|
||||
// v8::InvocationCallback's argument.
|
||||
__ lea(eax, ApiParameterOperand(1, returns_handle));
|
||||
__ lea(eax, ApiParameterOperand(2, returns_handle));
|
||||
__ mov(ApiParameterOperand(0, returns_handle), eax);
|
||||
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeInvocationCallback)
|
||||
: FUNCTION_ADDR(&InvokeFunctionCallback);
|
||||
|
||||
__ CallApiFunctionAndReturn(function_address,
|
||||
thunk_address,
|
||||
ApiParameterOperand(1, returns_handle),
|
||||
argc + kFastApiCallArguments + 1,
|
||||
returns_handle,
|
||||
kFastApiCallArguments + 1);
|
||||
@ -1406,7 +1417,9 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
|
||||
// array for v8::Arguments::values_, handler for name and pointer
|
||||
// to the values (it considered as smi in GC).
|
||||
const int kStackSpace = PropertyCallbackArguments::kArgsLength + 2;
|
||||
const int kApiArgc = 2;
|
||||
// Allocate space for opional callback address parameter in case
|
||||
// CPU profiler is active.
|
||||
const int kApiArgc = 2 + 1;
|
||||
|
||||
Address getter_address = v8::ToCData<Address>(callback->getter());
|
||||
bool returns_handle =
|
||||
@ -1422,7 +1435,13 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
|
||||
// garbage collection but instead return the allocation failure
|
||||
// object.
|
||||
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeAccessorGetter)
|
||||
: FUNCTION_ADDR(&InvokeAccessorGetterCallback);
|
||||
|
||||
__ CallApiFunctionAndReturn(getter_address,
|
||||
thunk_address,
|
||||
ApiParameterOperand(2, returns_handle),
|
||||
kStackSpace,
|
||||
returns_handle,
|
||||
6);
|
||||
|
@ -6911,13 +6911,6 @@ void DirectCEntryStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
||||
ExternalReference function) {
|
||||
__ li(t9, Operand(function));
|
||||
this->GenerateCall(masm, t9);
|
||||
}
|
||||
|
||||
|
||||
void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
||||
Register target) {
|
||||
__ Move(t9, target);
|
||||
|
@ -599,8 +599,6 @@ class DirectCEntryStub: public PlatformCodeStub {
|
||||
public:
|
||||
DirectCEntryStub() {}
|
||||
void Generate(MacroAssembler* masm);
|
||||
void GenerateCall(MacroAssembler* masm,
|
||||
ExternalReference function);
|
||||
void GenerateCall(MacroAssembler* masm, Register target);
|
||||
|
||||
private:
|
||||
|
@ -3909,6 +3909,9 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
|
||||
|
||||
|
||||
void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
|
||||
Address function_address,
|
||||
ExternalReference thunk_ref,
|
||||
Register thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset_from_fp) {
|
||||
@ -3947,11 +3950,30 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
|
||||
addiu(a0, fp, ExitFrameConstants::kStackSpaceOffset);
|
||||
}
|
||||
|
||||
Label profiler_disabled;
|
||||
Label end_profiler_check;
|
||||
bool* is_profiling_flag =
|
||||
isolate()->cpu_profiler()->is_profiling_address();
|
||||
STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
|
||||
li(t9, reinterpret_cast<int32_t>(is_profiling_flag));
|
||||
lb(t9, MemOperand(t9, 0));
|
||||
beq(t9, zero_reg, &profiler_disabled);
|
||||
|
||||
// Third parameter is the address of the actual getter function.
|
||||
li(thunk_last_arg, reinterpret_cast<int32_t>(function_address));
|
||||
li(t9, Operand(thunk_ref));
|
||||
jmp(&end_profiler_check);
|
||||
|
||||
bind(&profiler_disabled);
|
||||
li(t9, Operand(function));
|
||||
|
||||
bind(&end_profiler_check);
|
||||
|
||||
// Native call returns to the DirectCEntry stub which redirects to the
|
||||
// return address pushed on stack (could have moved after GC).
|
||||
// DirectCEntry stub itself is generated early and never moves.
|
||||
DirectCEntryStub stub;
|
||||
stub.GenerateCall(this, function);
|
||||
stub.GenerateCall(this, t9);
|
||||
|
||||
if (FLAG_log_timer_events) {
|
||||
FrameScope frame(this, StackFrame::MANUAL);
|
||||
|
@ -1235,6 +1235,9 @@ class MacroAssembler: public Assembler {
|
||||
// - space to be unwound on exit (includes the call JS arguments space and
|
||||
// the additional space allocated for the fast call).
|
||||
void CallApiFunctionAndReturn(ExternalReference function,
|
||||
Address function_address,
|
||||
ExternalReference thunk_ref,
|
||||
Register thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset_from_fp);
|
||||
|
@ -1394,6 +1394,9 @@ typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
|
||||
// Here, we pass the first argument in a0, because this function
|
||||
// does not return a struct.
|
||||
typedef void (*SimulatorRuntimeDirectApiCallNew)(int32_t arg0);
|
||||
typedef v8::Handle<v8::Value> (*SimulatorRuntimeProfilingApiCall)(
|
||||
int32_t arg0, int32_t arg1);
|
||||
typedef void (*SimulatorRuntimeProfilingApiCallNew)(int32_t arg0, int32_t arg1);
|
||||
|
||||
// This signature supports direct call to accessor getter callback.
|
||||
// See comment at SimulatorRuntimeDirectApiCall.
|
||||
@ -1402,6 +1405,10 @@ typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
|
||||
// See comment at SimulatorRuntimeDirectApiCallNew.
|
||||
typedef void (*SimulatorRuntimeDirectGetterCallNew)(int32_t arg0,
|
||||
int32_t arg1);
|
||||
typedef v8::Handle<v8::Value> (*SimulatorRuntimeProfilingGetterCall)(
|
||||
int32_t arg0, int32_t arg1, int32_t arg2);
|
||||
typedef void (*SimulatorRuntimeProfilingGetterCallNew)(
|
||||
int32_t arg0, int32_t arg1, int32_t arg2);
|
||||
|
||||
// Software interrupt instructions are used by the simulator to call into the
|
||||
// C-based V8 runtime. They are also used for debugging with simulator.
|
||||
@ -1570,6 +1577,30 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
||||
reinterpret_cast<SimulatorRuntimeDirectApiCallNew>(external);
|
||||
target(arg0);
|
||||
}
|
||||
} else if (
|
||||
redirection->type() == ExternalReference::PROFILING_API_CALL ||
|
||||
redirection->type() == ExternalReference::PROFILING_API_CALL_NEW) {
|
||||
if (redirection->type() == ExternalReference::PROFILING_API_CALL) {
|
||||
// See comment at type definition of SimulatorRuntimeDirectApiCall
|
||||
// for explanation of register usage.
|
||||
if (::v8::internal::FLAG_trace_sim) {
|
||||
PrintF("Call to host function at %p args %08x %08x\n",
|
||||
reinterpret_cast<void*>(external), arg1, arg2);
|
||||
}
|
||||
SimulatorRuntimeProfilingApiCall target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
|
||||
v8::Handle<v8::Value> result = target(arg1, arg2);
|
||||
*(reinterpret_cast<int*>(arg0)) = reinterpret_cast<int32_t>(*result);
|
||||
set_register(v0, arg0);
|
||||
} else {
|
||||
if (::v8::internal::FLAG_trace_sim) {
|
||||
PrintF("Call to host function at %p args %08x %08x\n",
|
||||
reinterpret_cast<void*>(external), arg0, arg1);
|
||||
}
|
||||
SimulatorRuntimeProfilingApiCallNew target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingApiCallNew>(external);
|
||||
target(arg0, arg1);
|
||||
}
|
||||
} else if (
|
||||
redirection->type() == ExternalReference::DIRECT_GETTER_CALL ||
|
||||
redirection->type() == ExternalReference::DIRECT_GETTER_CALL_NEW) {
|
||||
@ -1594,6 +1625,30 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
|
||||
reinterpret_cast<SimulatorRuntimeDirectGetterCallNew>(external);
|
||||
target(arg0, arg1);
|
||||
}
|
||||
} else if (
|
||||
redirection->type() == ExternalReference::PROFILING_GETTER_CALL ||
|
||||
redirection->type() == ExternalReference::PROFILING_GETTER_CALL_NEW) {
|
||||
if (redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
|
||||
// See comment at type definition of SimulatorRuntimeProfilingGetterCall
|
||||
// for explanation of register usage.
|
||||
if (::v8::internal::FLAG_trace_sim) {
|
||||
PrintF("Call to host function at %p args %08x %08x %08x\n",
|
||||
reinterpret_cast<void*>(external), arg1, arg2, arg3);
|
||||
}
|
||||
SimulatorRuntimeProfilingGetterCall target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
|
||||
v8::Handle<v8::Value> result = target(arg1, arg2, arg3);
|
||||
*(reinterpret_cast<int*>(arg0)) = reinterpret_cast<int32_t>(*result);
|
||||
set_register(v0, arg0);
|
||||
} else {
|
||||
if (::v8::internal::FLAG_trace_sim) {
|
||||
PrintF("Call to host function at %p args %08x %08x %08x\n",
|
||||
reinterpret_cast<void*>(external), arg0, arg1, arg2);
|
||||
}
|
||||
SimulatorRuntimeProfilingGetterCallNew target =
|
||||
reinterpret_cast<SimulatorRuntimeProfilingGetterCallNew>(external);
|
||||
target(arg0, arg1, arg2);
|
||||
}
|
||||
} else {
|
||||
SimulatorRuntimeCall target =
|
||||
reinterpret_cast<SimulatorRuntimeCall>(external);
|
||||
|
@ -932,6 +932,7 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
|
||||
!CallbackTable::ReturnsVoid(masm->isolate(), function_address);
|
||||
|
||||
Register first_arg = returns_handle ? a1 : a0;
|
||||
Register second_arg = returns_handle ? a2 : a1;
|
||||
|
||||
// first_arg = v8::Arguments&
|
||||
// Arguments is built at sp + 1 (sp is a reserved spot for ra).
|
||||
@ -958,8 +959,23 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
|
||||
ExternalReference(&fun,
|
||||
type,
|
||||
masm->isolate());
|
||||
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeInvocationCallback)
|
||||
: FUNCTION_ADDR(&InvokeFunctionCallback);
|
||||
ExternalReference::Type thunk_type =
|
||||
returns_handle ?
|
||||
ExternalReference::PROFILING_API_CALL :
|
||||
ExternalReference::PROFILING_API_CALL_NEW;
|
||||
ApiFunction thunk_fun(thunk_address);
|
||||
ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
|
||||
masm->isolate());
|
||||
|
||||
AllowExternalCallThatCantCauseGC scope(masm);
|
||||
__ CallApiFunctionAndReturn(ref,
|
||||
function_address,
|
||||
thunk_ref,
|
||||
second_arg,
|
||||
kStackUnwindSpace,
|
||||
returns_handle,
|
||||
kFastApiCallArguments + 1);
|
||||
@ -1452,6 +1468,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
|
||||
|
||||
Register first_arg = returns_handle ? a1 : a0;
|
||||
Register second_arg = returns_handle ? a2 : a1;
|
||||
Register third_arg = returns_handle ? a3 : a2;
|
||||
|
||||
__ mov(a2, scratch2()); // Saved in case scratch2 == a1.
|
||||
__ mov(first_arg, sp); // (first argument - see note below) = Handle<Name>
|
||||
@ -1472,14 +1489,28 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
|
||||
__ Addu(second_arg, sp, kPointerSize);
|
||||
|
||||
const int kStackUnwindSpace = kFastApiCallArguments + 1;
|
||||
|
||||
ApiFunction fun(getter_address);
|
||||
ExternalReference::Type type =
|
||||
returns_handle ?
|
||||
ExternalReference::DIRECT_GETTER_CALL :
|
||||
ExternalReference::DIRECT_GETTER_CALL_NEW;
|
||||
|
||||
ExternalReference ref = ExternalReference(&fun, type, isolate());
|
||||
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeAccessorGetter)
|
||||
: FUNCTION_ADDR(&InvokeAccessorGetterCallback);
|
||||
ExternalReference::Type thunk_type =
|
||||
returns_handle ?
|
||||
ExternalReference::PROFILING_GETTER_CALL :
|
||||
ExternalReference::PROFILING_GETTER_CALL_NEW;
|
||||
ApiFunction thunk_fun(thunk_address);
|
||||
ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
|
||||
isolate());
|
||||
__ CallApiFunctionAndReturn(ref,
|
||||
getter_address,
|
||||
thunk_ref,
|
||||
third_arg,
|
||||
kStackUnwindSpace,
|
||||
returns_handle,
|
||||
5);
|
||||
|
@ -496,9 +496,7 @@ class SamplerThread : public Thread {
|
||||
void SampleContext(Sampler* sampler) {
|
||||
if (!SignalHandler::Installed()) return;
|
||||
pthread_t tid = sampler->platform_data()->vm_tid();
|
||||
int result = pthread_kill(tid, SIGPROF);
|
||||
USE(result);
|
||||
ASSERT(result == 0);
|
||||
pthread_kill(tid, SIGPROF);
|
||||
}
|
||||
|
||||
#elif defined(__MACH__)
|
||||
|
@ -697,6 +697,8 @@ void MacroAssembler::PrepareCallApiFunction(int arg_stack_space,
|
||||
|
||||
|
||||
void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
|
||||
Address thunk_address,
|
||||
Register thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset) {
|
||||
@ -737,9 +739,29 @@ void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
|
||||
PopSafepointRegisters();
|
||||
}
|
||||
|
||||
|
||||
Label profiler_disabled;
|
||||
Label end_profiler_check;
|
||||
bool* is_profiling_flag =
|
||||
isolate()->cpu_profiler()->is_profiling_address();
|
||||
STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
|
||||
movq(rax, is_profiling_flag, RelocInfo::EXTERNAL_REFERENCE);
|
||||
cmpb(Operand(rax, 0), Immediate(0));
|
||||
j(zero, &profiler_disabled);
|
||||
|
||||
// Third parameter is the address of the actual getter function.
|
||||
movq(thunk_last_arg, function_address, RelocInfo::EXTERNAL_REFERENCE);
|
||||
movq(rax, thunk_address, RelocInfo::EXTERNAL_REFERENCE);
|
||||
jmp(&end_profiler_check);
|
||||
|
||||
bind(&profiler_disabled);
|
||||
// Call the api function!
|
||||
movq(rax, reinterpret_cast<int64_t>(function_address),
|
||||
RelocInfo::EXTERNAL_REFERENCE);
|
||||
|
||||
bind(&end_profiler_check);
|
||||
|
||||
// Call the api function!
|
||||
call(rax);
|
||||
|
||||
if (FLAG_log_timer_events) {
|
||||
|
@ -1239,6 +1239,8 @@ class MacroAssembler: public Assembler {
|
||||
// caller-save registers. Restores context. On return removes
|
||||
// stack_space * kPointerSize (GCed).
|
||||
void CallApiFunctionAndReturn(Address function_address,
|
||||
Address thunk_address,
|
||||
Register thunk_last_arg,
|
||||
int stack_space,
|
||||
bool returns_handle,
|
||||
int return_value_offset_from_rbp);
|
||||
|
@ -491,11 +491,14 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
||||
|
||||
#if defined(__MINGW64__)
|
||||
Register arguments_arg = rcx;
|
||||
Register callback_arg = rdx;
|
||||
#elif defined(_WIN64)
|
||||
// Win64 uses first register--rcx--for returned value.
|
||||
Register arguments_arg = returns_handle ? rdx : rcx;
|
||||
Register callback_arg = returns_handle ? r8 : rdx;
|
||||
#else
|
||||
Register arguments_arg = rdi;
|
||||
Register callback_arg = rsi;
|
||||
#endif
|
||||
|
||||
// Allocate the v8::Arguments structure in the arguments' space since
|
||||
@ -514,7 +517,13 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
||||
// v8::InvocationCallback's argument.
|
||||
__ lea(arguments_arg, StackSpaceOperand(0));
|
||||
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeInvocationCallback)
|
||||
: FUNCTION_ADDR(&InvokeFunctionCallback);
|
||||
|
||||
__ CallApiFunctionAndReturn(function_address,
|
||||
thunk_address,
|
||||
callback_arg,
|
||||
argc + kFastApiCallArguments + 1,
|
||||
returns_handle,
|
||||
kFastApiCallArguments + 1);
|
||||
@ -1318,13 +1327,16 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
|
||||
!CallbackTable::ReturnsVoid(isolate(), getter_address);
|
||||
|
||||
#if defined(__MINGW64__)
|
||||
Register getter_arg = r8;
|
||||
Register accessor_info_arg = rdx;
|
||||
Register name_arg = rcx;
|
||||
#elif defined(_WIN64)
|
||||
// Win64 uses first register--rcx--for returned value.
|
||||
Register getter_arg = returns_handle ? r9 : r8;
|
||||
Register accessor_info_arg = returns_handle ? r8 : rdx;
|
||||
Register name_arg = returns_handle ? rdx : rcx;
|
||||
#else
|
||||
Register getter_arg = rdx;
|
||||
Register accessor_info_arg = rsi;
|
||||
Register name_arg = rdi;
|
||||
#endif
|
||||
@ -1350,7 +1362,13 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
|
||||
// could be used to pass arguments.
|
||||
__ lea(accessor_info_arg, StackSpaceOperand(0));
|
||||
|
||||
Address thunk_address = returns_handle
|
||||
? FUNCTION_ADDR(&InvokeAccessorGetter)
|
||||
: FUNCTION_ADDR(&InvokeAccessorGetterCallback);
|
||||
|
||||
__ CallApiFunctionAndReturn(getter_address,
|
||||
thunk_address,
|
||||
getter_arg,
|
||||
kStackSpace,
|
||||
returns_handle,
|
||||
5);
|
||||
|
@ -804,7 +804,7 @@ THREADED_TEST(GlobalProperties) {
|
||||
|
||||
|
||||
template<typename T>
|
||||
static void CheckReturnValue(const T& t) {
|
||||
static void CheckReturnValue(const T& t, i::Address callback) {
|
||||
v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
|
||||
i::Object** o = *reinterpret_cast<i::Object***>(&rv);
|
||||
CHECK_EQ(v8::Isolate::GetCurrent(), t.GetIsolate());
|
||||
@ -817,45 +817,70 @@ static void CheckReturnValue(const T& t) {
|
||||
rv.Set(v8::Handle<v8::Object>());
|
||||
CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
|
||||
CHECK_EQ(is_runtime, (*o)->IsTheHole());
|
||||
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
|
||||
// If CPU profiler is active check that when API callback is invoked
|
||||
// VMState is set to EXTERNAL.
|
||||
if (isolate->cpu_profiler()->is_profiling()) {
|
||||
CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
|
||||
CHECK(isolate->external_callback());
|
||||
CHECK_EQ(callback, isolate->external_callback());
|
||||
}
|
||||
}
|
||||
|
||||
static v8::Handle<Value> handle_call(const v8::Arguments& args) {
|
||||
static v8::Handle<Value> handle_call_impl(
|
||||
const v8::Arguments& args,
|
||||
i::Address callback) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, callback);
|
||||
args.GetReturnValue().Set(v8_str("bad value"));
|
||||
return v8_num(102);
|
||||
}
|
||||
|
||||
static v8::Handle<Value> handle_call_2(const v8::Arguments& args) {
|
||||
return handle_call(args);
|
||||
static v8::Handle<Value> handle_call(const v8::Arguments& args) {
|
||||
return handle_call_impl(args, FUNCTION_ADDR(handle_call));
|
||||
}
|
||||
|
||||
static v8::Handle<Value> handle_call_indirect(const v8::Arguments& args) {
|
||||
static v8::Handle<Value> handle_call_2(const v8::Arguments& args) {
|
||||
return handle_call_impl(args, FUNCTION_ADDR(handle_call_2));
|
||||
}
|
||||
|
||||
static v8::Handle<Value> handle_call_indirect_impl(const v8::Arguments& args,
|
||||
i::Address callback) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, callback);
|
||||
args.GetReturnValue().Set(v8_str("bad value"));
|
||||
args.GetReturnValue().Set(v8_num(102));
|
||||
return v8::Handle<Value>();
|
||||
}
|
||||
|
||||
static v8::Handle<Value> handle_call_indirect_2(const v8::Arguments& args) {
|
||||
return handle_call_indirect(args);
|
||||
static v8::Handle<Value> handle_call_indirect(const v8::Arguments& args) {
|
||||
return handle_call_indirect_impl(args, FUNCTION_ADDR(handle_call_indirect));
|
||||
}
|
||||
|
||||
static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
|
||||
static v8::Handle<Value> handle_call_indirect_2(const v8::Arguments& args) {
|
||||
return handle_call_indirect_impl(args, FUNCTION_ADDR(handle_call_indirect_2));
|
||||
}
|
||||
|
||||
static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
|
||||
i::Address callback) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, callback);
|
||||
info.GetReturnValue().Set(v8_str("bad value"));
|
||||
info.GetReturnValue().Set(v8_num(102));
|
||||
}
|
||||
|
||||
static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
|
||||
return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
|
||||
}
|
||||
|
||||
static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
|
||||
return handle_callback(info);
|
||||
return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
|
||||
}
|
||||
|
||||
static v8::Handle<Value> construct_call(const v8::Arguments& args) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, FUNCTION_ADDR(construct_call));
|
||||
args.This()->Set(v8_str("x"), v8_num(1));
|
||||
args.This()->Set(v8_str("y"), v8_num(2));
|
||||
args.GetReturnValue().Set(v8_str("bad value"));
|
||||
@ -864,7 +889,7 @@ static v8::Handle<Value> construct_call(const v8::Arguments& args) {
|
||||
|
||||
static v8::Handle<Value> construct_call_indirect(const v8::Arguments& args) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, FUNCTION_ADDR(construct_call_indirect));
|
||||
args.This()->Set(v8_str("x"), v8_num(1));
|
||||
args.This()->Set(v8_str("y"), v8_num(2));
|
||||
args.GetReturnValue().Set(v8_str("bad value"));
|
||||
@ -875,7 +900,7 @@ static v8::Handle<Value> construct_call_indirect(const v8::Arguments& args) {
|
||||
static void construct_callback(
|
||||
const v8::FunctionCallbackInfo<Value>& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
|
||||
info.This()->Set(v8_str("x"), v8_num(1));
|
||||
info.This()->Set(v8_str("y"), v8_num(2));
|
||||
info.GetReturnValue().Set(v8_str("bad value"));
|
||||
@ -886,7 +911,7 @@ static void construct_callback(
|
||||
static v8::Handle<Value> Return239(
|
||||
Local<String> name, const AccessorInfo& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(Return239));
|
||||
info.GetReturnValue().Set(v8_str("bad value"));
|
||||
return v8_num(239);
|
||||
}
|
||||
@ -894,7 +919,7 @@ static v8::Handle<Value> Return239(
|
||||
static v8::Handle<Value> Return239Indirect(
|
||||
Local<String> name, const AccessorInfo& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(Return239Indirect));
|
||||
Handle<Value> value = v8_num(239);
|
||||
info.GetReturnValue().Set(v8_str("bad value"));
|
||||
info.GetReturnValue().Set(value);
|
||||
@ -904,7 +929,7 @@ static v8::Handle<Value> Return239Indirect(
|
||||
static void Return239Callback(
|
||||
Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
|
||||
info.GetReturnValue().Set(v8_str("bad value"));
|
||||
info.GetReturnValue().Set(v8_num(239));
|
||||
}
|
||||
@ -913,31 +938,56 @@ static void Return239Callback(
|
||||
template<typename Handler>
|
||||
static void TestFunctionTemplateInitializer(Handler handler,
|
||||
Handler handler_2) {
|
||||
// Test constructor calls.
|
||||
{
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
Local<v8::FunctionTemplate> fun_templ =
|
||||
v8::FunctionTemplate::New(handler);
|
||||
Local<Function> fun = fun_templ->GetFunction();
|
||||
env->Global()->Set(v8_str("obj"), fun);
|
||||
Local<Script> script = v8_compile("obj()");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(102, script->Run()->Int32Value());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
bool is_profiling = (i > 0);
|
||||
// Test constructor calls.
|
||||
{
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
|
||||
v8::Local<v8::String> profile_name = v8::String::New("my_profile1");
|
||||
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
|
||||
if (is_profiling) {
|
||||
cpu_profiler->StartCpuProfiling(profile_name);
|
||||
}
|
||||
|
||||
Local<v8::FunctionTemplate> fun_templ =
|
||||
v8::FunctionTemplate::New(handler);
|
||||
Local<Function> fun = fun_templ->GetFunction();
|
||||
env->Global()->Set(v8_str("obj"), fun);
|
||||
Local<Script> script = v8_compile("obj()");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(102, script->Run()->Int32Value());
|
||||
}
|
||||
|
||||
if (is_profiling) {
|
||||
cpu_profiler->StopCpuProfiling(profile_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Use SetCallHandler to initialize a function template, should work like the
|
||||
// previous one.
|
||||
{
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
|
||||
fun_templ->SetCallHandler(handler_2);
|
||||
Local<Function> fun = fun_templ->GetFunction();
|
||||
env->Global()->Set(v8_str("obj"), fun);
|
||||
Local<Script> script = v8_compile("obj()");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(102, script->Run()->Int32Value());
|
||||
// Use SetCallHandler to initialize a function template, should work like
|
||||
// the previous one.
|
||||
{
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
|
||||
v8::Local<v8::String> profile_name = v8::String::New("my_profile2");
|
||||
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
|
||||
if (is_profiling) {
|
||||
cpu_profiler->StartCpuProfiling(profile_name);
|
||||
}
|
||||
|
||||
Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
|
||||
fun_templ->SetCallHandler(handler_2);
|
||||
Local<Function> fun = fun_templ->GetFunction();
|
||||
env->Global()->Set(v8_str("obj"), fun);
|
||||
Local<Script> script = v8_compile("obj()");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(102, script->Run()->Int32Value());
|
||||
}
|
||||
|
||||
if (is_profiling) {
|
||||
cpu_profiler->DeleteAllCpuProfiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -946,25 +996,39 @@ static void TestFunctionTemplateInitializer(Handler handler,
|
||||
template<typename Constructor, typename Accessor>
|
||||
static void TestFunctionTemplateAccessor(Constructor constructor,
|
||||
Accessor accessor) {
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
Local<v8::FunctionTemplate> fun_templ =
|
||||
v8::FunctionTemplate::New(constructor);
|
||||
fun_templ->SetClassName(v8_str("funky"));
|
||||
fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
|
||||
Local<Function> fun = fun_templ->GetFunction();
|
||||
env->Global()->Set(v8_str("obj"), fun);
|
||||
Local<Value> result = v8_compile("(new obj()).toString()")->Run();
|
||||
CHECK_EQ(v8_str("[object funky]"), result);
|
||||
CompileRun("var obj_instance = new obj();");
|
||||
Local<Script> script;
|
||||
script = v8_compile("obj_instance.x");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(1, script->Run()->Int32Value());
|
||||
}
|
||||
script = v8_compile("obj_instance.m");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(239, script->Run()->Int32Value());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
bool is_profiling = (i > 0);
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
|
||||
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
|
||||
if (is_profiling) {
|
||||
v8::Local<v8::String> profile_name = v8::String::New("my_profile1");
|
||||
cpu_profiler->StartCpuProfiling(profile_name);
|
||||
}
|
||||
|
||||
Local<v8::FunctionTemplate> fun_templ =
|
||||
v8::FunctionTemplate::New(constructor);
|
||||
fun_templ->SetClassName(v8_str("funky"));
|
||||
fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
|
||||
Local<Function> fun = fun_templ->GetFunction();
|
||||
env->Global()->Set(v8_str("obj"), fun);
|
||||
Local<Value> result = v8_compile("(new obj()).toString()")->Run();
|
||||
CHECK_EQ(v8_str("[object funky]"), result);
|
||||
CompileRun("var obj_instance = new obj();");
|
||||
Local<Script> script;
|
||||
script = v8_compile("obj_instance.x");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(1, script->Run()->Int32Value());
|
||||
}
|
||||
script = v8_compile("obj_instance.m");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(239, script->Run()->Int32Value());
|
||||
}
|
||||
|
||||
if (is_profiling) {
|
||||
cpu_profiler->DeleteAllCpuProfiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -982,41 +1046,55 @@ THREADED_TEST(FunctionTemplate) {
|
||||
|
||||
static v8::Handle<v8::Value> SimpleDirectCallback(const v8::Arguments& args) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, FUNCTION_ADDR(SimpleDirectCallback));
|
||||
args.GetReturnValue().Set(v8_str("bad value"));
|
||||
return v8_num(51423 + args.Length());
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> SimpleIndirectCallback(const v8::Arguments& args) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, FUNCTION_ADDR(SimpleIndirectCallback));
|
||||
args.GetReturnValue().Set(v8_num(51423 + args.Length()));
|
||||
return v8::Handle<v8::Value>();
|
||||
}
|
||||
|
||||
static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
|
||||
info.GetReturnValue().Set(v8_num(51423 + info.Length()));
|
||||
}
|
||||
|
||||
|
||||
template<typename Callback>
|
||||
static void TestSimpleCallback(Callback callback) {
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
|
||||
object_template->Set("callback", v8::FunctionTemplate::New(callback));
|
||||
v8::Local<v8::Object> object = object_template->NewInstance();
|
||||
(*env)->Global()->Set(v8_str("callback_object"), object);
|
||||
v8::Handle<v8::Script> script;
|
||||
script = v8_compile("callback_object.callback(17)");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(51424, script->Run()->Int32Value());
|
||||
}
|
||||
script = v8_compile("callback_object.callback(17, 24)");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(51425, script->Run()->Int32Value());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
bool is_profiling = i;
|
||||
LocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
|
||||
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
|
||||
if (is_profiling) {
|
||||
v8::Local<v8::String> profile_name = v8::String::New("my_profile1");
|
||||
cpu_profiler->StartCpuProfiling(profile_name);
|
||||
}
|
||||
|
||||
v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
|
||||
object_template->Set("callback", v8::FunctionTemplate::New(callback));
|
||||
v8::Local<v8::Object> object = object_template->NewInstance();
|
||||
(*env)->Global()->Set(v8_str("callback_object"), object);
|
||||
v8::Handle<v8::Script> script;
|
||||
script = v8_compile("callback_object.callback(17)");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(51424, script->Run()->Int32Value());
|
||||
}
|
||||
script = v8_compile("callback_object.callback(17, 24)");
|
||||
for (int i = 0; i < 30; i++) {
|
||||
CHECK_EQ(51425, script->Run()->Int32Value());
|
||||
}
|
||||
|
||||
if (is_profiling) {
|
||||
cpu_profiler->DeleteAllCpuProfiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1048,35 +1126,35 @@ static bool fast_return_value_object_is_empty = false;
|
||||
template<>
|
||||
void FastReturnValueCallback<int32_t>(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(FastReturnValueCallback<int32_t>));
|
||||
info.GetReturnValue().Set(fast_return_value_int32);
|
||||
}
|
||||
|
||||
template<>
|
||||
void FastReturnValueCallback<uint32_t>(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(FastReturnValueCallback<uint32_t>));
|
||||
info.GetReturnValue().Set(fast_return_value_uint32);
|
||||
}
|
||||
|
||||
template<>
|
||||
void FastReturnValueCallback<double>(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(FastReturnValueCallback<double>));
|
||||
info.GetReturnValue().Set(kFastReturnValueDouble);
|
||||
}
|
||||
|
||||
template<>
|
||||
void FastReturnValueCallback<bool>(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(FastReturnValueCallback<bool>));
|
||||
info.GetReturnValue().Set(fast_return_value_bool);
|
||||
}
|
||||
|
||||
template<>
|
||||
void FastReturnValueCallback<void>(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(FastReturnValueCallback<void>));
|
||||
switch (fast_return_value_void) {
|
||||
case kNullReturnValue:
|
||||
info.GetReturnValue().SetNull();
|
||||
@ -2053,7 +2131,7 @@ v8::Handle<v8::Object> bottom;
|
||||
static void CheckThisIndexedPropertyHandler(
|
||||
uint32_t index,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2061,7 +2139,7 @@ static void CheckThisIndexedPropertyHandler(
|
||||
static void CheckThisNamedPropertyHandler(
|
||||
Local<String> name,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2070,7 +2148,7 @@ void CheckThisIndexedPropertySetter(
|
||||
uint32_t index,
|
||||
Local<Value> value,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2080,7 +2158,7 @@ void CheckThisNamedPropertySetter(
|
||||
Local<String> property,
|
||||
Local<Value> value,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2088,7 +2166,7 @@ void CheckThisNamedPropertySetter(
|
||||
void CheckThisIndexedPropertyQuery(
|
||||
uint32_t index,
|
||||
const v8::PropertyCallbackInfo<v8::Integer>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2097,7 +2175,7 @@ void CheckThisIndexedPropertyQuery(
|
||||
void CheckThisNamedPropertyQuery(
|
||||
Local<String> property,
|
||||
const v8::PropertyCallbackInfo<v8::Integer>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2106,7 +2184,7 @@ void CheckThisNamedPropertyQuery(
|
||||
void CheckThisIndexedPropertyDeleter(
|
||||
uint32_t index,
|
||||
const v8::PropertyCallbackInfo<v8::Boolean>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2115,7 +2193,7 @@ void CheckThisIndexedPropertyDeleter(
|
||||
void CheckThisNamedPropertyDeleter(
|
||||
Local<String> property,
|
||||
const v8::PropertyCallbackInfo<v8::Boolean>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2123,7 +2201,7 @@ void CheckThisNamedPropertyDeleter(
|
||||
|
||||
void CheckThisIndexedPropertyEnumerator(
|
||||
const v8::PropertyCallbackInfo<v8::Array>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -2131,7 +2209,7 @@ void CheckThisIndexedPropertyEnumerator(
|
||||
|
||||
void CheckThisNamedPropertyEnumerator(
|
||||
const v8::PropertyCallbackInfo<v8::Array>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CHECK(info.This()->Equals(bottom));
|
||||
}
|
||||
@ -10637,7 +10715,7 @@ THREADED_TEST(InterceptorCallICCachedFromGlobal) {
|
||||
static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
|
||||
const AccessorInfo& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
|
||||
int* call_count =
|
||||
reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
|
||||
++(*call_count);
|
||||
@ -10650,7 +10728,7 @@ static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
|
||||
static v8::Handle<Value> FastApiCallback_TrivialSignature(
|
||||
const v8::Arguments& args) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
CHECK_EQ(isolate, args.GetIsolate());
|
||||
CHECK_EQ(args.This(), args.Holder());
|
||||
@ -10661,7 +10739,7 @@ static v8::Handle<Value> FastApiCallback_TrivialSignature(
|
||||
static v8::Handle<Value> FastApiCallback_SimpleSignature(
|
||||
const v8::Arguments& args) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
CheckReturnValue(args);
|
||||
CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
CHECK_EQ(isolate, args.GetIsolate());
|
||||
CHECK_EQ(args.This()->GetPrototype(), args.Holder());
|
||||
@ -10749,7 +10827,7 @@ static Handle<Value> DoDirectGetter() {
|
||||
|
||||
static v8::Handle<v8::Value> DirectGetter(Local<String> name,
|
||||
const v8::AccessorInfo& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(DirectGetter));
|
||||
info.GetReturnValue().Set(v8_str("Garbage"));
|
||||
return DoDirectGetter();
|
||||
}
|
||||
@ -10757,7 +10835,7 @@ static v8::Handle<v8::Value> DirectGetter(Local<String> name,
|
||||
static v8::Handle<v8::Value> DirectGetterIndirect(
|
||||
Local<String> name,
|
||||
const v8::AccessorInfo& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(DirectGetterIndirect));
|
||||
info.GetReturnValue().Set(DoDirectGetter());
|
||||
return v8::Handle<v8::Value>();
|
||||
}
|
||||
@ -10765,7 +10843,7 @@ static v8::Handle<v8::Value> DirectGetterIndirect(
|
||||
static void DirectGetterCallback(
|
||||
Local<String> name,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
CheckReturnValue(info);
|
||||
CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
|
||||
info.GetReturnValue().Set(DoDirectGetter());
|
||||
}
|
||||
|
||||
|
@ -802,9 +802,7 @@ TEST(NativeAccessorMonomorphicIC) {
|
||||
|
||||
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
|
||||
const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
||||
// TODO(yurys): in LoadIC should be changed to report external callback
|
||||
// invocation. See r13768 where it was LoadCallbackProperty was removed.
|
||||
// GetChild(startNode, "get foo");
|
||||
GetChild(startNode, "get foo");
|
||||
GetChild(startNode, "set foo");
|
||||
|
||||
cpu_profiler->DeleteAllCpuProfiles();
|
||||
@ -911,9 +909,8 @@ TEST(NativeMethodMonomorphicIC) {
|
||||
|
||||
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
|
||||
GetChild(root, "start");
|
||||
// TODO(yurys): in CallIC should be changed to report external callback
|
||||
// invocation.
|
||||
// GetChild(startNode, "fooMethod");
|
||||
const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
||||
GetChild(startNode, "fooMethod");
|
||||
|
||||
cpu_profiler->DeleteAllCpuProfiles();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user