aff1f3788b
This is preparatory cleanup work for eventually tracking the functions (rather than concrete closures) in the CALL_IC, also for builtins like the default PromiseCapability [[Resolve]] and [[Reject]] functions. It adds a new FeedbackCell type, which is used by JSFunctions consistently now to reference the feedback vector (or undefined if not the function is not compiled yet or is a native/asm.js function). This also changes the calling convention for FastNewClosure builtin and the JSCreateClosure operator in TurboFan to carry the FeedbackCell here instead of the parent FeedbackVector and the slot index. In addition we eliminate the now unused %InterpreterNewClosure runtime function. Bug: v8:2206, v8:7253, v8:7310 Change-Id: Ib4ce456e276e0273e57c163dcdd0b33abf863656 Reviewed-on: https://chromium-review.googlesource.com/928403 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#51474}
141 lines
4.5 KiB
C++
141 lines
4.5 KiB
C++
// Copyright 2015 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef V8_TEST_CCTEST_INTERPRETER_INTERPRETER_TESTER_H_
|
|
#define V8_TEST_CCTEST_INTERPRETER_INTERPRETER_TESTER_H_
|
|
|
|
#include "src/v8.h"
|
|
|
|
#include "src/api.h"
|
|
#include "src/execution.h"
|
|
#include "src/handles.h"
|
|
#include "src/interpreter/bytecode-array-builder.h"
|
|
#include "src/interpreter/interpreter.h"
|
|
#include "test/cctest/cctest.h"
|
|
#include "test/cctest/test-feedback-vector.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace interpreter {
|
|
|
|
MaybeHandle<Object> CallInterpreter(Isolate* isolate,
|
|
Handle<JSFunction> function);
|
|
template <class... A>
|
|
static MaybeHandle<Object> CallInterpreter(Isolate* isolate,
|
|
Handle<JSFunction> function,
|
|
A... args) {
|
|
Handle<Object> argv[] = {args...};
|
|
return Execution::Call(isolate, function,
|
|
isolate->factory()->undefined_value(), sizeof...(args),
|
|
argv);
|
|
}
|
|
|
|
template <class... A>
|
|
class InterpreterCallable {
|
|
public:
|
|
InterpreterCallable(Isolate* isolate, Handle<JSFunction> function)
|
|
: isolate_(isolate), function_(function) {}
|
|
virtual ~InterpreterCallable() {}
|
|
|
|
MaybeHandle<Object> operator()(A... args) {
|
|
return CallInterpreter(isolate_, function_, args...);
|
|
}
|
|
|
|
FeedbackVector* vector() const { return function_->feedback_vector(); }
|
|
|
|
private:
|
|
Isolate* isolate_;
|
|
Handle<JSFunction> function_;
|
|
};
|
|
|
|
class InterpreterTester {
|
|
public:
|
|
InterpreterTester(Isolate* isolate, const char* source,
|
|
MaybeHandle<BytecodeArray> bytecode,
|
|
MaybeHandle<FeedbackMetadata> feedback_metadata,
|
|
const char* filter);
|
|
|
|
InterpreterTester(Isolate* isolate, Handle<BytecodeArray> bytecode,
|
|
MaybeHandle<FeedbackMetadata> feedback_metadata =
|
|
MaybeHandle<FeedbackMetadata>(),
|
|
const char* filter = kFunctionName);
|
|
|
|
InterpreterTester(Isolate* isolate, const char* source,
|
|
const char* filter = kFunctionName);
|
|
|
|
virtual ~InterpreterTester();
|
|
|
|
template <class... A>
|
|
InterpreterCallable<A...> GetCallable() {
|
|
return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>());
|
|
}
|
|
|
|
Local<Message> CheckThrowsReturnMessage();
|
|
|
|
static Handle<Object> NewObject(const char* script);
|
|
|
|
static Handle<String> GetName(Isolate* isolate, const char* name);
|
|
|
|
static std::string SourceForBody(const char* body);
|
|
|
|
static std::string function_name();
|
|
|
|
static const char kFunctionName[];
|
|
|
|
// Expose raw RegisterList construction to tests.
|
|
static RegisterList NewRegisterList(int first_reg_index, int register_count) {
|
|
return RegisterList(first_reg_index, register_count);
|
|
}
|
|
|
|
private:
|
|
Isolate* isolate_;
|
|
const char* source_;
|
|
MaybeHandle<BytecodeArray> bytecode_;
|
|
MaybeHandle<FeedbackMetadata> feedback_metadata_;
|
|
|
|
template <class... A>
|
|
Handle<JSFunction> GetBytecodeFunction() {
|
|
Handle<JSFunction> function;
|
|
if (source_) {
|
|
CompileRun(source_);
|
|
v8::Local<v8::Context> context =
|
|
v8::Isolate::GetCurrent()->GetCurrentContext();
|
|
Local<Function> api_function =
|
|
Local<Function>::Cast(CcTest::global()
|
|
->Get(context, v8_str(kFunctionName))
|
|
.ToLocalChecked());
|
|
function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
|
|
} else {
|
|
int arg_count = sizeof...(A);
|
|
std::string source("(function " + function_name() + "(");
|
|
for (int i = 0; i < arg_count; i++) {
|
|
source += i == 0 ? "a" : ", a";
|
|
}
|
|
source += "){})";
|
|
function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
|
|
*v8::Local<v8::Function>::Cast(CompileRun(source.c_str()))));
|
|
function->set_code(*BUILTIN_CODE(isolate_, InterpreterEntryTrampoline));
|
|
}
|
|
|
|
if (!bytecode_.is_null()) {
|
|
function->shared()->set_function_data(*bytecode_.ToHandleChecked());
|
|
}
|
|
if (!feedback_metadata_.is_null()) {
|
|
function->set_feedback_cell(isolate_->heap()->many_closures_cell());
|
|
function->shared()->set_feedback_metadata(
|
|
*feedback_metadata_.ToHandleChecked());
|
|
JSFunction::EnsureFeedbackVector(function);
|
|
}
|
|
return function;
|
|
}
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InterpreterTester);
|
|
};
|
|
|
|
} // namespace interpreter
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_TEST_CCTEST_INTERPRETER_INTERPRETER_TESTER_H_
|