v8/test/cctest/compiler/function-tester.cc
Benedikt Meurer aff1f3788b [cleanup] Introduce a dedicated FeedbackCell.
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}
2018-02-22 13:18:48 +00:00

181 lines
5.8 KiB
C++

// Copyright 2014 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 "test/cctest/compiler/function-tester.h"
#include "src/api.h"
#include "src/compilation-info.h"
#include "src/compiler.h"
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline.h"
#include "src/execution.h"
#include "src/handles.h"
#include "src/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "test/cctest/cctest.h"
namespace v8 {
namespace internal {
namespace compiler {
FunctionTester::FunctionTester(const char* source, uint32_t flags)
: isolate(main_isolate()),
function((FLAG_allow_natives_syntax = true, NewFunction(source))),
flags_(flags) {
Compile(function);
const uint32_t supported_flags = CompilationInfo::kInliningEnabled;
CHECK_EQ(0u, flags_ & ~supported_flags);
}
FunctionTester::FunctionTester(Graph* graph, int param_count)
: isolate(main_isolate()),
function(NewFunction(BuildFunction(param_count).c_str())),
flags_(0) {
CompileGraph(graph);
}
FunctionTester::FunctionTester(Handle<Code> code, int param_count)
: isolate(main_isolate()),
function((FLAG_allow_natives_syntax = true,
NewFunction(BuildFunction(param_count).c_str()))),
flags_(0) {
CHECK(!code.is_null());
Compile(function);
function->set_code(*code);
}
FunctionTester::FunctionTester(Handle<Code> code) : FunctionTester(code, 0) {}
void FunctionTester::CheckThrows(Handle<Object> a) {
TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
MaybeHandle<Object> no_result = Call(a);
CHECK(isolate->has_pending_exception());
CHECK(try_catch.HasCaught());
CHECK(no_result.is_null());
isolate->OptionalRescheduleException(true);
}
void FunctionTester::CheckThrows(Handle<Object> a, Handle<Object> b) {
TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
MaybeHandle<Object> no_result = Call(a, b);
CHECK(isolate->has_pending_exception());
CHECK(try_catch.HasCaught());
CHECK(no_result.is_null());
isolate->OptionalRescheduleException(true);
}
v8::Local<v8::Message> FunctionTester::CheckThrowsReturnMessage(
Handle<Object> a, Handle<Object> b) {
TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
MaybeHandle<Object> no_result = Call(a, b);
CHECK(isolate->has_pending_exception());
CHECK(try_catch.HasCaught());
CHECK(no_result.is_null());
isolate->OptionalRescheduleException(true);
CHECK(!try_catch.Message().IsEmpty());
return try_catch.Message();
}
void FunctionTester::CheckCall(Handle<Object> expected, Handle<Object> a,
Handle<Object> b, Handle<Object> c,
Handle<Object> d) {
Handle<Object> result = Call(a, b, c, d).ToHandleChecked();
CHECK(expected->SameValue(*result));
}
Handle<JSFunction> FunctionTester::NewFunction(const char* source) {
return Handle<JSFunction>::cast(v8::Utils::OpenHandle(
*v8::Local<v8::Function>::Cast(CompileRun(source))));
}
Handle<JSObject> FunctionTester::NewObject(const char* source) {
return Handle<JSObject>::cast(
v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(CompileRun(source))));
}
Handle<String> FunctionTester::Val(const char* string) {
return isolate->factory()->InternalizeUtf8String(string);
}
Handle<Object> FunctionTester::Val(double value) {
return isolate->factory()->NewNumber(value);
}
Handle<Object> FunctionTester::infinity() {
return isolate->factory()->infinity_value();
}
Handle<Object> FunctionTester::minus_infinity() { return Val(-V8_INFINITY); }
Handle<Object> FunctionTester::nan() { return isolate->factory()->nan_value(); }
Handle<Object> FunctionTester::undefined() {
return isolate->factory()->undefined_value();
}
Handle<Object> FunctionTester::null() {
return isolate->factory()->null_value();
}
Handle<Object> FunctionTester::true_value() {
return isolate->factory()->true_value();
}
Handle<Object> FunctionTester::false_value() {
return isolate->factory()->false_value();
}
Handle<JSFunction> FunctionTester::ForMachineGraph(Graph* graph,
int param_count) {
JSFunction* p = nullptr;
{ // because of the implicit handle scope of FunctionTester.
FunctionTester f(graph, param_count);
p = *f.function;
}
return Handle<JSFunction>(p); // allocated in outer handle scope.
}
Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) {
Handle<SharedFunctionInfo> shared(function->shared());
ParseInfo parse_info(shared);
CompilationInfo info(parse_info.zone(), function->GetIsolate(), shared,
function);
if (flags_ & CompilationInfo::kInliningEnabled) {
info.MarkAsInliningEnabled();
}
CHECK(function->is_compiled() ||
Compiler::Compile(function, Compiler::CLEAR_EXCEPTION));
CHECK(info.shared_info()->HasBytecodeArray());
JSFunction::EnsureFeedbackVector(function);
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, function->GetIsolate());
CHECK(!code.is_null());
info.dependencies()->Commit(code);
info.context()->native_context()->AddOptimizedCode(*code);
function->set_code(*code);
return function;
}
// Compile the given machine graph instead of the source of the function
// and replace the JSFunction's code with the result.
Handle<JSFunction> FunctionTester::CompileGraph(Graph* graph) {
Handle<SharedFunctionInfo> shared(function->shared());
ParseInfo parse_info(shared);
CompilationInfo info(parse_info.zone(), function->GetIsolate(), shared,
function);
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, function->GetIsolate(), graph);
CHECK(!code.is_null());
function->set_code(*code);
return function;
}
} // namespace compiler
} // namespace internal
} // namespace v8