2016-03-22 11:35:09 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
#include "src/v8.h"
|
|
|
|
|
2017-01-20 14:21:34 +00:00
|
|
|
#include "src/api.h"
|
2016-03-22 11:35:09 +00:00
|
|
|
#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...);
|
|
|
|
}
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
FeedbackVector* vector() const { return function_->feedback_vector(); }
|
2017-01-26 10:03:00 +00:00
|
|
|
|
2016-03-22 11:35:09 +00:00
|
|
|
private:
|
|
|
|
Isolate* isolate_;
|
|
|
|
Handle<JSFunction> function_;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
const char kFunctionName[] = "f";
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
class InterpreterTester {
|
|
|
|
public:
|
|
|
|
InterpreterTester(Isolate* isolate, const char* source,
|
|
|
|
MaybeHandle<BytecodeArray> bytecode,
|
2017-02-07 14:05:02 +00:00
|
|
|
MaybeHandle<FeedbackMetadata> feedback_metadata,
|
2016-03-22 11:35:09 +00:00
|
|
|
const char* filter);
|
|
|
|
|
|
|
|
InterpreterTester(Isolate* isolate, Handle<BytecodeArray> bytecode,
|
2017-02-07 14:05:02 +00:00
|
|
|
MaybeHandle<FeedbackMetadata> feedback_metadata =
|
|
|
|
MaybeHandle<FeedbackMetadata>(),
|
2016-03-22 11:35:09 +00:00
|
|
|
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();
|
|
|
|
|
|
|
|
private:
|
|
|
|
Isolate* isolate_;
|
|
|
|
const char* source_;
|
|
|
|
MaybeHandle<BytecodeArray> bytecode_;
|
2017-02-07 14:05:02 +00:00
|
|
|
MaybeHandle<FeedbackMetadata> feedback_metadata_;
|
2016-03-22 11:35:09 +00:00
|
|
|
|
|
|
|
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->ReplaceCode(
|
|
|
|
*isolate_->builtins()->InterpreterEntryTrampoline());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bytecode_.is_null()) {
|
|
|
|
function->shared()->set_function_data(*bytecode_.ToHandleChecked());
|
|
|
|
}
|
2017-01-26 10:03:00 +00:00
|
|
|
if (!feedback_metadata_.is_null()) {
|
2017-02-08 08:33:33 +00:00
|
|
|
function->set_feedback_vector_cell(isolate_->heap()->undefined_cell());
|
2017-01-26 10:03:00 +00:00
|
|
|
function->shared()->set_feedback_metadata(
|
|
|
|
*feedback_metadata_.ToHandleChecked());
|
|
|
|
JSFunction::EnsureLiterals(function);
|
2016-03-22 11:35:09 +00:00
|
|
|
}
|
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(InterpreterTester);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace interpreter
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|