[snapshot] Move builtins generation into mksnapshot

and out of the main library. This saves about 5% of binary size
(800KB on x64, 373KB on android_arm).

Only the GN build is supported; the GYP build is maintained working
but does not support the feature.

BUG=v8:6055
CQ_INCLUDE_TRYBOTS=master.tryserver.v8:v8_linux_nosnap_rel;

Review-Url: https://codereview.chromium.org/2760233005
Cr-Commit-Position: refs/heads/master@{#44412}
This commit is contained in:
jkummerow 2017-04-05 06:28:48 -07:00 committed by Commit bot
parent 4f8b76068d
commit 4782bc0df8
30 changed files with 788 additions and 416 deletions

View File

@ -810,6 +810,7 @@ source_set("v8_maybe_snapshot") {
} else {
# Ignore v8_use_external_startup_data setting if no snapshot is used.
public_deps = [
":v8_builtins_setup",
":v8_nosnapshot",
]
}
@ -823,7 +824,6 @@ v8_source_set("v8_nosnapshot") {
":js2c_experimental_extras",
":js2c_extras",
":v8_base",
":v8_builtins_generators",
]
sources = [
@ -849,7 +849,6 @@ v8_source_set("v8_snapshot") {
":js2c_experimental_extras",
":js2c_extras",
":v8_base",
":v8_builtins_generators",
]
public_deps = [
# This should be public so downstream targets can declare the snapshot
@ -862,6 +861,7 @@ v8_source_set("v8_snapshot") {
"$target_gen_dir/extras-libraries.cc",
"$target_gen_dir/libraries.cc",
"$target_gen_dir/snapshot.cc",
"src/setup-isolate-deserialize.cc",
]
configs = [ ":internal_config" ]
@ -876,7 +876,6 @@ if (v8_use_external_startup_data) {
":js2c_experimental_extras",
":js2c_extras",
":v8_base",
":v8_builtins_generators",
]
public_deps = [
":natives_blob",
@ -884,6 +883,7 @@ if (v8_use_external_startup_data) {
]
sources = [
"src/setup-isolate-deserialize.cc",
"src/snapshot/natives-external.cc",
"src/snapshot/snapshot-external.cc",
]
@ -893,7 +893,11 @@ if (v8_use_external_startup_data) {
}
v8_source_set("v8_builtins_generators") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
visibility = [
":*",
"test/cctest:*",
"test/unittests:*",
]
deps = [
":v8_base",
@ -910,6 +914,7 @@ v8_source_set("v8_builtins_generators") {
"src/builtins/builtins-async-generator-gen.cc",
"src/builtins/builtins-async-iterator-gen.cc",
"src/builtins/builtins-boolean-gen.cc",
"src/builtins/builtins-call-gen.cc",
"src/builtins/builtins-constructor-gen.cc",
"src/builtins/builtins-constructor-gen.h",
"src/builtins/builtins-constructor.h",
@ -923,6 +928,7 @@ v8_source_set("v8_builtins_generators") {
"src/builtins/builtins-handler-gen.cc",
"src/builtins/builtins-ic-gen.cc",
"src/builtins/builtins-internal-gen.cc",
"src/builtins/builtins-interpreter-gen.cc",
"src/builtins/builtins-math-gen.cc",
"src/builtins/builtins-number-gen.cc",
"src/builtins/builtins-object-gen.cc",
@ -936,6 +942,7 @@ v8_source_set("v8_builtins_generators") {
"src/builtins/builtins-typedarray-gen.cc",
"src/builtins/builtins-utils-gen.h",
"src/builtins/builtins-wasm-gen.cc",
"src/builtins/setup-builtins-internal.cc",
"src/ic/accessor-assembler.cc",
"src/ic/accessor-assembler.h",
"src/ic/binary-op-assembler.cc",
@ -948,6 +955,8 @@ v8_source_set("v8_builtins_generators") {
"src/interpreter/interpreter-generator.h",
"src/interpreter/interpreter-intrinsics-generator.cc",
"src/interpreter/interpreter-intrinsics-generator.h",
"src/interpreter/setup-interpreter-internal.cc",
"src/interpreter/setup-interpreter.h",
]
if (v8_current_cpu == "x86") {
@ -1000,6 +1009,21 @@ v8_source_set("v8_builtins_generators") {
configs = [ ":internal_config" ]
}
v8_source_set("v8_builtins_setup") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
deps = [
":v8_builtins_generators",
]
sources = [
### gcmole(all) ###
"src/setup-isolate-full.cc",
]
configs = [ ":internal_config" ]
}
# This is split out to be a non-code containing target that the Chromium browser
# DLL can depend upon to get only a version string.
v8_header_set("v8_version") {
@ -1840,6 +1864,7 @@ v8_source_set("v8_base") {
"src/runtime/runtime.h",
"src/safepoint-table.cc",
"src/safepoint-table.h",
"src/setup-isolate.h",
"src/signature.h",
"src/simulator.h",
"src/small-pointer-list.h",
@ -2603,6 +2628,7 @@ if (current_toolchain == v8_snapshot_toolchain) {
deps = [
":v8_base",
":v8_builtins_setup",
":v8_libbase",
":v8_libplatform",
":v8_nosnapshot",

View File

@ -137,5 +137,8 @@
], # conditions
}, # Release
}, # configurations
'defines': [
'V8_GYP_BUILD',
], # defines
}, # target_defaults
}

View File

@ -18,6 +18,7 @@ include_rules = [
"+src/interpreter/bytecode-register.h",
"+src/interpreter/bytecodes.h",
"+src/interpreter/interpreter.h",
"+src/interpreter/setup-interpreter.h",
"-src/trap-handler",
"+src/trap-handler/trap-handler.h",
"+testing/gtest/include/gtest/gtest_prod.h",

View File

@ -8181,6 +8181,12 @@ Isolate* Isolate::GetCurrent() {
Isolate* Isolate::New(const Isolate::CreateParams& params) {
i::Isolate* isolate = new i::Isolate(false);
return IsolateNewImpl(isolate, params);
}
// This is separate so that tests can provide a different |isolate|.
Isolate* IsolateNewImpl(internal::Isolate* isolate,
const v8::Isolate::CreateParams& params) {
Isolate* v8_isolate = reinterpret_cast<Isolate*>(isolate);
CHECK(params.array_buffer_allocator != NULL);
isolate->set_array_buffer_allocator(params.array_buffer_allocator);

View File

@ -347,6 +347,8 @@ OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
#undef MAKE_OPEN_HANDLE
#undef OPEN_HANDLE_LIST
extern Isolate* IsolateNewImpl(internal::Isolate* isolate,
const Isolate::CreateParams& params);
namespace internal {
@ -645,7 +647,6 @@ void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
(!blocks_.is_empty() && prev_limit != NULL));
}
// Interceptor functions called from generated inline caches to notify
// CPU profiler that external callbacks are invoked.
void InvokeAccessorGetterCallback(

View File

@ -0,0 +1,95 @@
// Copyright 2017 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/builtins/builtins.h"
#include "src/globals.h"
#include "src/isolate.h"
#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
void Builtins::Generate_CallFunction_ReceiverIsNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_CallFunction_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_CallFunction_ReceiverIsAny(MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kAny,
TailCallMode::kDisallow);
}
void Builtins::Generate_TailCallFunction_ReceiverIsNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCallFunction_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCallFunction_ReceiverIsAny(MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow);
}
void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) {
Generate_CallBoundFunctionImpl(masm, TailCallMode::kDisallow);
}
void Builtins::Generate_TailCallBoundFunction(MacroAssembler* masm) {
Generate_CallBoundFunctionImpl(masm, TailCallMode::kAllow);
}
void Builtins::Generate_Call_ReceiverIsNullOrUndefined(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_Call_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_Call_ReceiverIsAny(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kDisallow);
}
void Builtins::Generate_TailCall_ReceiverIsNullOrUndefined(
MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCall_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCall_ReceiverIsAny(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow);
}
void Builtins::Generate_CallForwardVarargs(MacroAssembler* masm) {
Generate_CallForwardVarargs(masm, masm->isolate()->builtins()->Call());
}
void Builtins::Generate_CallFunctionForwardVarargs(MacroAssembler* masm) {
Generate_CallForwardVarargs(masm,
masm->isolate()->builtins()->CallFunction());
}
} // namespace internal
} // namespace v8

View File

@ -4,8 +4,8 @@
#include "src/builtins/builtins-utils.h"
#include "src/builtins/builtins.h"
#include "src/handles-inl.h"
#include "src/isolate.h"
#include "src/macro-assembler.h"
#include "src/objects-inl.h"
namespace v8 {
@ -78,86 +78,5 @@ Handle<Code> Builtins::CallBoundFunction(TailCallMode tail_call_mode) {
return Handle<Code>::null();
}
void Builtins::Generate_CallFunction_ReceiverIsNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_CallFunction_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_CallFunction_ReceiverIsAny(MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kAny,
TailCallMode::kDisallow);
}
void Builtins::Generate_TailCallFunction_ReceiverIsNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCallFunction_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCallFunction_ReceiverIsAny(MacroAssembler* masm) {
Generate_CallFunction(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow);
}
void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) {
Generate_CallBoundFunctionImpl(masm, TailCallMode::kDisallow);
}
void Builtins::Generate_TailCallBoundFunction(MacroAssembler* masm) {
Generate_CallBoundFunctionImpl(masm, TailCallMode::kAllow);
}
void Builtins::Generate_Call_ReceiverIsNullOrUndefined(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_Call_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kDisallow);
}
void Builtins::Generate_Call_ReceiverIsAny(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kDisallow);
}
void Builtins::Generate_TailCall_ReceiverIsNullOrUndefined(
MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCall_ReceiverIsNotNullOrUndefined(
MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kNotNullOrUndefined,
TailCallMode::kAllow);
}
void Builtins::Generate_TailCall_ReceiverIsAny(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow);
}
void Builtins::Generate_CallForwardVarargs(MacroAssembler* masm) {
Generate_CallForwardVarargs(masm, masm->isolate()->builtins()->Call());
}
void Builtins::Generate_CallFunctionForwardVarargs(MacroAssembler* masm) {
Generate_CallForwardVarargs(masm,
masm->isolate()->builtins()->CallFunction());
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,58 @@
// Copyright 2017 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/builtins/builtins.h"
#include "src/globals.h"
#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kOther);
}
void Builtins::Generate_InterpreterPushArgsAndCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kJSFunction);
}
void Builtins::Generate_InterpreterPushArgsAndCallWithFinalSpread(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kWithFinalSpread);
}
void Builtins::Generate_InterpreterPushArgsAndTailCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kAllow, InterpreterPushArgsMode::kOther);
}
void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kAllow, InterpreterPushArgsMode::kJSFunction);
}
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kOther);
}
void Builtins::Generate_InterpreterPushArgsAndConstructWithFinalSpread(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kWithFinalSpread);
}
void Builtins::Generate_InterpreterPushArgsAndConstructFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kJSFunction);
}
} // namespace internal
} // namespace v8

View File

@ -4,6 +4,8 @@
#include "src/builtins/builtins-utils.h"
#include "src/builtins/builtins.h"
#include "src/globals.h"
#include "src/handles-inl.h"
#include "src/objects-inl.h"
namespace v8 {
@ -32,34 +34,6 @@ Handle<Code> Builtins::InterpreterPushArgsAndCall(
return Handle<Code>::null();
}
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kOther);
}
void Builtins::Generate_InterpreterPushArgsAndCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kJSFunction);
}
void Builtins::Generate_InterpreterPushArgsAndCallWithFinalSpread(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kWithFinalSpread);
}
void Builtins::Generate_InterpreterPushArgsAndTailCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kAllow, InterpreterPushArgsMode::kOther);
}
void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kAllow, InterpreterPushArgsMode::kJSFunction);
}
Handle<Code> Builtins::InterpreterPushArgsAndConstruct(
InterpreterPushArgsMode mode) {
switch (mode) {
@ -74,22 +48,5 @@ Handle<Code> Builtins::InterpreterPushArgsAndConstruct(
return Handle<Code>::null();
}
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kOther);
}
void Builtins::Generate_InterpreterPushArgsAndConstructWithFinalSpread(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kWithFinalSpread);
}
void Builtins::Generate_InterpreterPushArgsAndConstructFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kJSFunction);
}
} // namespace internal
} // namespace v8

View File

@ -7,10 +7,6 @@
#include "src/assembler-inl.h"
#include "src/builtins/builtins-descriptors.h"
#include "src/callable.h"
#include "src/code-events.h"
#include "src/compiler/code-assembler.h"
#include "src/ic/ic-state.h"
#include "src/interface-descriptors.h"
#include "src/isolate.h"
#include "src/macro-assembler.h"
#include "src/objects-inl.h"
@ -29,173 +25,6 @@ Builtins::Builtins() : initialized_(false) {
Builtins::~Builtins() {}
namespace {
void PostBuildProfileAndTracing(Isolate* isolate, Code* code,
const char* name) {
PROFILE(isolate, CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
AbstractCode::cast(code), name));
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_builtin_code) {
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
OFStream os(trace_scope.file());
os << "Builtin: " << name << "\n";
code->Disassemble(name, os);
os << "\n";
}
#endif
}
typedef void (*MacroAssemblerGenerator)(MacroAssembler*);
typedef void (*CodeAssemblerGenerator)(compiler::CodeAssemblerState*);
Code* BuildWithMacroAssembler(Isolate* isolate,
MacroAssemblerGenerator generator,
Code::Flags flags, const char* s_name) {
HandleScope scope(isolate);
const size_t buffer_size = 32 * KB;
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
DCHECK(!masm.has_frame());
generator(&masm);
CodeDesc desc;
masm.GetCode(&desc);
Handle<Code> code =
isolate->factory()->NewCode(desc, flags, masm.CodeObject());
PostBuildProfileAndTracing(isolate, *code, s_name);
return *code;
}
Code* BuildAdaptor(Isolate* isolate, Address builtin_address,
Builtins::ExitFrameType exit_frame_type, Code::Flags flags,
const char* name) {
HandleScope scope(isolate);
const size_t buffer_size = 32 * KB;
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
DCHECK(!masm.has_frame());
Builtins::Generate_Adaptor(&masm, builtin_address, exit_frame_type);
CodeDesc desc;
masm.GetCode(&desc);
Handle<Code> code =
isolate->factory()->NewCode(desc, flags, masm.CodeObject());
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
// Builder for builtins implemented in TurboFan with JS linkage.
Code* BuildWithCodeStubAssemblerJS(Isolate* isolate,
CodeAssemblerGenerator generator, int argc,
Code::Flags flags, const char* name) {
HandleScope scope(isolate);
Zone zone(isolate->allocator(), ZONE_NAME);
const int argc_with_recv =
(argc == SharedFunctionInfo::kDontAdaptArgumentsSentinel) ? 0 : argc + 1;
compiler::CodeAssemblerState state(isolate, &zone, argc_with_recv, flags,
name);
generator(&state);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
// Builder for builtins implemented in TurboFan with CallStub linkage.
Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
CodeAssemblerGenerator generator,
CallDescriptors::Key interface_descriptor,
Code::Flags flags, const char* name,
int result_size) {
HandleScope scope(isolate);
Zone zone(isolate->allocator(), ZONE_NAME);
// The interface descriptor with given key must be initialized at this point
// and this construction just queries the details from the descriptors table.
CallInterfaceDescriptor descriptor(isolate, interface_descriptor);
// Ensure descriptor is already initialized.
DCHECK_LE(0, descriptor.GetRegisterParameterCount());
compiler::CodeAssemblerState state(isolate, &zone, descriptor, flags, name,
result_size);
generator(&state);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
} // anonymous namespace
void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
DCHECK(!initialized_);
// Create a scope for the handles in the builtins.
HandleScope scope(isolate);
if (create_heap_objects) {
int index = 0;
const Code::Flags kBuiltinFlags = Code::ComputeFlags(Code::BUILTIN);
Code* code;
#define BUILD_CPP(Name) \
code = BuildAdaptor(isolate, FUNCTION_ADDR(Builtin_##Name), BUILTIN_EXIT, \
kBuiltinFlags, #Name); \
builtins_[index++] = code;
#define BUILD_API(Name) \
code = BuildAdaptor(isolate, FUNCTION_ADDR(Builtin_##Name), EXIT, \
kBuiltinFlags, #Name); \
builtins_[index++] = code;
#define BUILD_TFJ(Name, Argc, ...) \
code = BuildWithCodeStubAssemblerJS(isolate, &Generate_##Name, Argc, \
kBuiltinFlags, #Name); \
builtins_[index++] = code;
#define BUILD_TFS(Name, InterfaceDescriptor, result_size) \
{ InterfaceDescriptor##Descriptor descriptor(isolate); } \
code = BuildWithCodeStubAssemblerCS(isolate, &Generate_##Name, \
CallDescriptors::InterfaceDescriptor, \
kBuiltinFlags, #Name, result_size); \
builtins_[index++] = code;
#define BUILD_TFH(Name, Kind, Extra, InterfaceDescriptor) \
{ InterfaceDescriptor##Descriptor descriptor(isolate); } \
/* Return size for IC builtins/handlers is always 1. */ \
code = BuildWithCodeStubAssemblerCS( \
isolate, &Generate_##Name, CallDescriptors::InterfaceDescriptor, \
Code::ComputeFlags(Code::Kind, Extra), #Name, 1); \
builtins_[index++] = code;
#define BUILD_ASM(Name) \
code = \
BuildWithMacroAssembler(isolate, Generate_##Name, kBuiltinFlags, #Name); \
builtins_[index++] = code;
BUILTIN_LIST(BUILD_CPP, BUILD_API, BUILD_TFJ, BUILD_TFS, BUILD_TFH,
BUILD_ASM, BUILD_ASM);
#undef BUILD_CPP
#undef BUILD_API
#undef BUILD_TFJ
#undef BUILD_TFS
#undef BUILD_TFH
#undef BUILD_ASM
CHECK_EQ(builtin_count, index);
for (int i = 0; i < builtin_count; i++) {
Code::cast(builtins_[i])->set_builtin_index(i);
}
#define SET_PROMISE_REJECTION_PREDICTION(Name) \
Code::cast(builtins_[k##Name])->set_is_promise_rejection(true);
BUILTIN_PROMISE_REJECTION_PREDICTION_LIST(SET_PROMISE_REJECTION_PREDICTION)
#undef SET_PROMISE_REJECTION_PREDICTION
#define SET_EXCEPTION_CAUGHT_PREDICTION(Name) \
Code::cast(builtins_[k##Name])->set_is_exception_caught(true);
BUILTIN_EXCEPTION_CAUGHT_PREDICTION_LIST(SET_EXCEPTION_CAUGHT_PREDICTION)
#undef SET_EXCEPTION_CAUGHT_PREDICTION
#define SET_CODE_NON_TAGGED_PARAMS(Name) \
Code::cast(builtins_[k##Name])->set_has_tagged_params(false);
BUILTINS_WITH_UNTAGGED_PARAMS(SET_CODE_NON_TAGGED_PARAMS)
#undef SET_CODE_NON_TAGGED_PARAMS
}
// Mark as initialized.
initialized_ = true;
}
void Builtins::TearDown() { initialized_ = false; }
void Builtins::IterateBuiltins(ObjectVisitor* v) {

View File

@ -28,9 +28,6 @@ class Builtins {
public:
~Builtins();
// Generate all builtin code objects. Should be called once during
// isolate initialization.
void SetUp(Isolate* isolate, bool create_heap_objects);
void TearDown();
// Garbage collection support.
@ -107,6 +104,11 @@ class Builtins {
private:
Builtins();
// Used by SetupIsolateDelegate.
void MarkInitialized() {
DCHECK(!initialized_);
initialized_ = true;
}
static void Generate_CallFunction(MacroAssembler* masm,
ConvertReceiverMode mode,
@ -145,6 +147,7 @@ class Builtins {
bool initialized_;
friend class Isolate;
friend class SetupIsolateDelegate;
DISALLOW_COPY_AND_ASSIGN(Builtins);
};

View File

@ -0,0 +1,195 @@
// Copyright 2017 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/setup-isolate.h"
#include "src/builtins/builtins.h"
#include "src/code-events.h"
#include "src/compiler/code-assembler.h"
#include "src/interface-descriptors.h"
#include "src/isolate.h"
namespace v8 {
namespace internal {
// Forward declarations for C++ builtins.
#define FORWARD_DECLARE(Name) \
Object* Builtin_##Name(int argc, Object** args, Isolate* isolate);
BUILTIN_LIST_C(FORWARD_DECLARE)
namespace {
void PostBuildProfileAndTracing(Isolate* isolate, Code* code,
const char* name) {
PROFILE(isolate, CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
AbstractCode::cast(code), name));
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_builtin_code) {
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
OFStream os(trace_scope.file());
os << "Builtin: " << name << "\n";
code->Disassemble(name, os);
os << "\n";
}
#endif
}
typedef void (*MacroAssemblerGenerator)(MacroAssembler*);
typedef void (*CodeAssemblerGenerator)(compiler::CodeAssemblerState*);
Code* BuildWithMacroAssembler(Isolate* isolate,
MacroAssemblerGenerator generator,
Code::Flags flags, const char* s_name) {
HandleScope scope(isolate);
const size_t buffer_size = 32 * KB;
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
DCHECK(!masm.has_frame());
generator(&masm);
CodeDesc desc;
masm.GetCode(&desc);
Handle<Code> code =
isolate->factory()->NewCode(desc, flags, masm.CodeObject());
PostBuildProfileAndTracing(isolate, *code, s_name);
return *code;
}
Code* BuildAdaptor(Isolate* isolate, Address builtin_address,
Builtins::ExitFrameType exit_frame_type, Code::Flags flags,
const char* name) {
HandleScope scope(isolate);
const size_t buffer_size = 32 * KB;
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
DCHECK(!masm.has_frame());
Builtins::Generate_Adaptor(&masm, builtin_address, exit_frame_type);
CodeDesc desc;
masm.GetCode(&desc);
Handle<Code> code =
isolate->factory()->NewCode(desc, flags, masm.CodeObject());
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
// Builder for builtins implemented in TurboFan with JS linkage.
Code* BuildWithCodeStubAssemblerJS(Isolate* isolate,
CodeAssemblerGenerator generator, int argc,
Code::Flags flags, const char* name) {
HandleScope scope(isolate);
Zone zone(isolate->allocator(), ZONE_NAME);
const int argc_with_recv =
(argc == SharedFunctionInfo::kDontAdaptArgumentsSentinel) ? 0 : argc + 1;
compiler::CodeAssemblerState state(isolate, &zone, argc_with_recv, flags,
name);
generator(&state);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
// Builder for builtins implemented in TurboFan with CallStub linkage.
Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
CodeAssemblerGenerator generator,
CallDescriptors::Key interface_descriptor,
Code::Flags flags, const char* name,
int result_size) {
HandleScope scope(isolate);
Zone zone(isolate->allocator(), ZONE_NAME);
// The interface descriptor with given key must be initialized at this point
// and this construction just queries the details from the descriptors table.
CallInterfaceDescriptor descriptor(isolate, interface_descriptor);
// Ensure descriptor is already initialized.
DCHECK_LE(0, descriptor.GetRegisterParameterCount());
compiler::CodeAssemblerState state(isolate, &zone, descriptor, flags, name,
result_size);
generator(&state);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
} // anonymous namespace
void SetupIsolateDelegate::AddBuiltin(Builtins* builtins, int index,
Code* code) {
builtins->builtins_[index] = code;
code->set_builtin_index(index);
}
void SetupIsolateDelegate::SetupBuiltinsInternal(Isolate* isolate) {
Builtins* builtins = isolate->builtins();
DCHECK(!builtins->initialized_);
// Create a scope for the handles in the builtins.
HandleScope scope(isolate);
int index = 0;
const Code::Flags kBuiltinFlags = Code::ComputeFlags(Code::BUILTIN);
Code* code;
#define BUILD_CPP(Name) \
code = BuildAdaptor(isolate, FUNCTION_ADDR(Builtin_##Name), \
Builtins::BUILTIN_EXIT, kBuiltinFlags, #Name); \
AddBuiltin(builtins, index++, code);
#define BUILD_API(Name) \
code = BuildAdaptor(isolate, FUNCTION_ADDR(Builtin_##Name), Builtins::EXIT, \
kBuiltinFlags, #Name); \
AddBuiltin(builtins, index++, code);
#define BUILD_TFJ(Name, Argc, ...) \
code = BuildWithCodeStubAssemblerJS(isolate, &Builtins::Generate_##Name, \
Argc, kBuiltinFlags, #Name); \
AddBuiltin(builtins, index++, code);
#define BUILD_TFS(Name, InterfaceDescriptor, result_size) \
{ InterfaceDescriptor##Descriptor descriptor(isolate); } \
code = BuildWithCodeStubAssemblerCS(isolate, &Builtins::Generate_##Name, \
CallDescriptors::InterfaceDescriptor, \
kBuiltinFlags, #Name, result_size); \
AddBuiltin(builtins, index++, code);
#define BUILD_TFH(Name, Kind, Extra, InterfaceDescriptor) \
{ InterfaceDescriptor##Descriptor descriptor(isolate); } \
/* Return size for IC builtins/handlers is always 1. */ \
code = BuildWithCodeStubAssemblerCS(isolate, &Builtins::Generate_##Name, \
CallDescriptors::InterfaceDescriptor, \
Code::ComputeFlags(Code::Kind, Extra), \
#Name, 1); \
AddBuiltin(builtins, index++, code);
#define BUILD_ASM(Name) \
code = BuildWithMacroAssembler(isolate, Builtins::Generate_##Name, \
kBuiltinFlags, #Name); \
AddBuiltin(builtins, index++, code);
BUILTIN_LIST(BUILD_CPP, BUILD_API, BUILD_TFJ, BUILD_TFS, BUILD_TFH, BUILD_ASM,
BUILD_ASM);
#undef BUILD_CPP
#undef BUILD_API
#undef BUILD_TFJ
#undef BUILD_TFS
#undef BUILD_TFH
#undef BUILD_ASM
CHECK_EQ(Builtins::builtin_count, index);
#define SET_PROMISE_REJECTION_PREDICTION(Name) \
Code::cast(builtins->builtins_[Builtins::k##Name]) \
->set_is_promise_rejection(true);
BUILTIN_PROMISE_REJECTION_PREDICTION_LIST(SET_PROMISE_REJECTION_PREDICTION)
#undef SET_PROMISE_REJECTION_PREDICTION
#define SET_EXCEPTION_CAUGHT_PREDICTION(Name) \
Code::cast(builtins->builtins_[Builtins::k##Name]) \
->set_is_exception_caught(true);
BUILTIN_EXCEPTION_CAUGHT_PREDICTION_LIST(SET_EXCEPTION_CAUGHT_PREDICTION)
#undef SET_EXCEPTION_CAUGHT_PREDICTION
#define SET_CODE_NON_TAGGED_PARAMS(Name) \
Code::cast(builtins->builtins_[Builtins::k##Name]) \
->set_has_tagged_params(false);
BUILTINS_WITH_UNTAGGED_PARAMS(SET_CODE_NON_TAGGED_PARAMS)
#undef SET_CODE_NON_TAGGED_PARAMS
isolate->builtins()->MarkInitialized();
}
} // namespace internal
} // namespace v8

View File

@ -13,9 +13,9 @@
#include "src/counters.h"
#include "src/interpreter/bytecode-generator.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter-generator.h"
#include "src/log.h"
#include "src/objects.h"
#include "src/setup-isolate.h"
namespace v8 {
namespace internal {
@ -73,11 +73,6 @@ class InterpreterCompilationJob final : public CompilationJob {
Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) {
memset(dispatch_table_, 0, sizeof(dispatch_table_));
}
void Interpreter::Initialize() {
if (!ShouldInitializeDispatchTable()) return;
HandleScope scope(isolate_);
if (FLAG_trace_ignition_dispatches) {
static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
@ -86,71 +81,6 @@ void Interpreter::Initialize() {
memset(bytecode_dispatch_counters_table_.get(), 0,
sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount);
}
// Generate bytecode handlers for all bytecodes and scales.
const OperandScale kOperandScales[] = {
#define VALUE(Name, _) OperandScale::k##Name,
OPERAND_SCALE_LIST(VALUE)
#undef VALUE
};
for (OperandScale operand_scale : kOperandScales) {
#define GENERATE_CODE(Name, ...) \
InstallBytecodeHandler(isolate_, Bytecode::k##Name, operand_scale);
BYTECODE_LIST(GENERATE_CODE)
#undef GENERATE_CODE
}
// Fill unused entries will the illegal bytecode handler.
size_t illegal_index =
GetDispatchTableIndex(Bytecode::kIllegal, OperandScale::kSingle);
for (size_t index = 0; index < arraysize(dispatch_table_); ++index) {
if (dispatch_table_[index] == nullptr) {
dispatch_table_[index] = dispatch_table_[illegal_index];
}
}
// Initialization should have been successful.
DCHECK(IsDispatchTableInitialized());
}
bool Interpreter::ReuseExistingHandler(Bytecode bytecode,
OperandScale operand_scale) {
size_t index = GetDispatchTableIndex(bytecode, operand_scale);
switch (bytecode) {
case Bytecode::kCallProperty:
case Bytecode::kCallProperty0:
case Bytecode::kCallProperty1:
case Bytecode::kCallProperty2: {
const int offset = static_cast<int>(Bytecode::kCallProperty) -
static_cast<int>(Bytecode::kCall);
STATIC_ASSERT(offset ==
static_cast<int>(Bytecode::kCallProperty0) -
static_cast<int>(Bytecode::kCall0));
STATIC_ASSERT(offset ==
static_cast<int>(Bytecode::kCallProperty1) -
static_cast<int>(Bytecode::kCall1));
STATIC_ASSERT(offset ==
static_cast<int>(Bytecode::kCallProperty2) -
static_cast<int>(Bytecode::kCall2));
CHECK_LT(offset, index);
dispatch_table_[index] = dispatch_table_[index - offset];
return true;
break;
}
default:
return false;
}
}
void Interpreter::InstallBytecodeHandler(Isolate* isolate, Bytecode bytecode,
OperandScale operand_scale) {
if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return;
if (ReuseExistingHandler(bytecode, operand_scale)) return;
size_t index = GetDispatchTableIndex(bytecode, operand_scale);
Handle<Code> code = GenerateBytecodeHandler(isolate, bytecode, operand_scale);
dispatch_table_[index] = code->entry();
}
Code* Interpreter::GetBytecodeHandler(Bytecode bytecode,
@ -285,16 +215,6 @@ bool Interpreter::IsDispatchTableInitialized() {
return dispatch_table_[0] != nullptr;
}
bool Interpreter::ShouldInitializeDispatchTable() {
if (FLAG_trace_ignition || FLAG_trace_ignition_codegen ||
FLAG_trace_ignition_dispatches) {
// Regenerate table to add bytecode tracing operations, print the assembly
// code generated by TurboFan or instrument handlers with dispatch counters.
return true;
}
return !IsDispatchTableInitialized();
}
const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) {
#ifdef ENABLE_DISASSEMBLER
#define RETURN_NAME(Name, ...) \

View File

@ -23,6 +23,7 @@ class Isolate;
class Callable;
class CompilationInfo;
class CompilationJob;
class SetupIsolateDelegate;
namespace interpreter {
@ -33,9 +34,6 @@ class Interpreter {
explicit Interpreter(Isolate* isolate);
virtual ~Interpreter() {}
// Initializes the interpreter dispatch table.
void Initialize();
// Returns the interrupt budget which should be used for the profiler counter.
static int InterruptBudget();
@ -65,14 +63,8 @@ class Interpreter {
static const int kCodeSizeMultiplier = 24;
private:
// In the case of bytecodes that share handler implementations, copy the code
// into the bytecode's dispatcher table entry and return true.
bool ReuseExistingHandler(Bytecode bytecode, OperandScale operand_scale);
// Generates handler for given |bytecode| and |operand_scale|
// and installs it into the dispatch table.
void InstallBytecodeHandler(Isolate* isolate, Bytecode bytecode,
OperandScale operand_scale);
friend class SetupInterpreter;
friend class v8::internal::SetupIsolateDelegate;
uintptr_t GetDispatchCounter(Bytecode from, Bytecode to) const;
@ -81,7 +73,6 @@ class Interpreter {
OperandScale operand_scale);
bool IsDispatchTableInitialized();
bool ShouldInitializeDispatchTable();
static const int kNumberOfWideVariants = 3;
static const int kDispatchTableSize = kNumberOfWideVariants * (kMaxUInt8 + 1);

View File

@ -0,0 +1,94 @@
// Copyright 2017 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/interpreter/setup-interpreter.h"
#include "src/handles-inl.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter-generator.h"
#include "src/interpreter/interpreter.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
namespace interpreter {
// static
void SetupInterpreter::InstallBytecodeHandlers(Interpreter* interpreter) {
DCHECK(!interpreter->IsDispatchTableInitialized());
HandleScope scope(interpreter->isolate_);
Address* dispatch_table = interpreter->dispatch_table_;
// Generate bytecode handlers for all bytecodes and scales.
const OperandScale kOperandScales[] = {
#define VALUE(Name, _) OperandScale::k##Name,
OPERAND_SCALE_LIST(VALUE)
#undef VALUE
};
for (OperandScale operand_scale : kOperandScales) {
#define GENERATE_CODE(Name, ...) \
InstallBytecodeHandler(interpreter->isolate_, dispatch_table, \
Bytecode::k##Name, operand_scale);
BYTECODE_LIST(GENERATE_CODE)
#undef GENERATE_CODE
}
// Fill unused entries will the illegal bytecode handler.
size_t illegal_index = Interpreter::GetDispatchTableIndex(
Bytecode::kIllegal, OperandScale::kSingle);
for (size_t index = 0; index < Interpreter::kDispatchTableSize; ++index) {
if (dispatch_table[index] == nullptr) {
dispatch_table[index] = dispatch_table[illegal_index];
}
}
// Initialization should have been successful.
DCHECK(interpreter->IsDispatchTableInitialized());
}
// static
bool SetupInterpreter::ReuseExistingHandler(Address* dispatch_table,
Bytecode bytecode,
OperandScale operand_scale) {
size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
switch (bytecode) {
case Bytecode::kCallProperty:
case Bytecode::kCallProperty0:
case Bytecode::kCallProperty1:
case Bytecode::kCallProperty2: {
const int offset = static_cast<int>(Bytecode::kCallProperty) -
static_cast<int>(Bytecode::kCall);
STATIC_ASSERT(offset == static_cast<int>(Bytecode::kCallProperty0) -
static_cast<int>(Bytecode::kCall0));
STATIC_ASSERT(offset == static_cast<int>(Bytecode::kCallProperty1) -
static_cast<int>(Bytecode::kCall1));
STATIC_ASSERT(offset == static_cast<int>(Bytecode::kCallProperty2) -
static_cast<int>(Bytecode::kCall2));
CHECK_LT(offset, index);
dispatch_table[index] = dispatch_table[index - offset];
return true;
break;
}
default:
return false;
}
}
// static
void SetupInterpreter::InstallBytecodeHandler(Isolate* isolate,
Address* dispatch_table,
Bytecode bytecode,
OperandScale operand_scale) {
if (!Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) return;
if (ReuseExistingHandler(dispatch_table, bytecode, operand_scale)) return;
size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
Handle<Code> code = GenerateBytecodeHandler(isolate, bytecode, operand_scale);
dispatch_table[index] = code->entry();
}
} // namespace interpreter
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,37 @@
// Copyright 2017 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_INTERPRETER_SETUP_INTERPRETER_H_
#define V8_INTERPRETER_SETUP_INTERPRETER_H_
#include "src/interpreter/bytecode-operands.h"
#include "src/interpreter/bytecodes.h"
namespace v8 {
namespace internal {
namespace interpreter {
class Interpreter;
class SetupInterpreter {
public:
static void InstallBytecodeHandlers(Interpreter* interpreter);
private:
// In the case of bytecodes that share handler implementations, copy the code
// into the bytecode's dispatcher table entry and return true.
static bool ReuseExistingHandler(Address* dispatch_table, Bytecode bytecode,
OperandScale operand_scale);
// Generates handler for given |bytecode| and |operand_scale|
// and installs it into the |dispatch_table|.
static void InstallBytecodeHandler(Isolate* isolate, Address* dispatch_table,
Bytecode bytecode,
OperandScale operand_scale);
};
} // namespace interpreter
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETER_SETUP_INTERPRETER_H_

View File

@ -44,6 +44,7 @@
#include "src/prototype.h"
#include "src/regexp/regexp-stack.h"
#include "src/runtime-profiler.h"
#include "src/setup-isolate.h"
#include "src/simulator.h"
#include "src/snapshot/deserializer.h"
#include "src/tracing/tracing-category-observer.h"
@ -2227,6 +2228,7 @@ Isolate::Isolate(bool enable_serializer)
global_handles_(NULL),
eternal_handles_(NULL),
thread_manager_(NULL),
setup_delegate_(NULL),
regexp_stack_(NULL),
date_cache_(NULL),
call_descriptor_data_(NULL),
@ -2666,7 +2668,10 @@ bool Isolate::Init(Deserializer* des) {
InitializeThreadLocal();
bootstrapper_->Initialize(create_heap_objects);
builtins_.SetUp(this, create_heap_objects);
if (setup_delegate_ == nullptr) {
setup_delegate_ = new SetupIsolateDelegate();
}
setup_delegate_->SetupBuiltins(this, create_heap_objects);
if (create_heap_objects) heap_.CreateFixedStubs();
if (FLAG_log_internal_timer_events) {
@ -2693,10 +2698,12 @@ bool Isolate::Init(Deserializer* des) {
}
load_stub_cache_->Initialize();
store_stub_cache_->Initialize();
interpreter_->Initialize();
setup_delegate_->SetupInterpreter(interpreter_, create_heap_objects);
heap_.NotifyDeserializationComplete();
}
delete setup_delegate_;
setup_delegate_ = nullptr;
// Finish initialization of ThreadLocal after deserialization is done.
clear_pending_exception();

View File

@ -26,6 +26,8 @@
#include "src/runtime/runtime.h"
#include "src/zone/zone.h"
class TestIsolate;
namespace v8 {
namespace base {
@ -74,6 +76,7 @@ class OptimizingCompileDispatcher;
class RegExpStack;
class RuntimeProfiler;
class SaveContext;
class SetupIsolateDelegate;
class StatsTable;
class StringTracker;
class StubCache;
@ -1422,6 +1425,7 @@ class Isolate {
ThreadManager* thread_manager_;
RuntimeState runtime_state_;
Builtins builtins_;
SetupIsolateDelegate* setup_delegate_;
unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
unibrow::Mapping<unibrow::Ecma262Canonicalize>
@ -1560,6 +1564,7 @@ class Isolate {
friend class v8::Locker;
friend class v8::Unlocker;
friend class v8::SnapshotCreator;
friend class ::TestIsolate;
friend v8::StartupData v8::V8::CreateSnapshotDataBlob(const char*);
friend v8::StartupData v8::V8::WarmUpSnapshotDataBlob(v8::StartupData,
const char*);

View File

@ -0,0 +1,36 @@
// Copyright 2017 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/setup-isolate.h"
#include "src/base/logging.h"
#include "src/interpreter/interpreter.h"
#include "src/isolate.h"
#include "src/ostreams.h"
namespace v8 {
namespace internal {
void SetupIsolateDelegate::SetupBuiltins(Isolate* isolate,
bool create_heap_objects) {
DCHECK(!create_heap_objects);
// No actual work to be done; builtins will be deserialized from the snapshot.
isolate->builtins()->MarkInitialized();
}
void SetupIsolateDelegate::SetupInterpreter(
interpreter::Interpreter* interpreter, bool create_heap_objects) {
#ifdef V8_USE_SNAPSHOT
if (FLAG_trace_ignition || FLAG_trace_ignition_codegen ||
FLAG_trace_ignition_dispatches) {
OFStream os(stdout);
os << "Warning: --trace-ignition-* flags must be passed at mksnapshot "
<< "time or used with nosnapshot builds." << std::endl;
}
#endif
DCHECK(interpreter->IsDispatchTableInitialized());
}
} // namespace internal
} // namespace v8

41
src/setup-isolate-full.cc Normal file
View File

@ -0,0 +1,41 @@
// Copyright 2017 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/setup-isolate.h"
#include "src/base/logging.h"
#include "src/interpreter/setup-interpreter.h"
#include "src/isolate.h"
namespace v8 {
namespace internal {
void SetupIsolateDelegate::SetupBuiltins(Isolate* isolate,
bool create_heap_objects) {
#ifdef V8_GYP_BUILD
// Compatibility hack to keep the deprecated GYP build working.
if (create_heap_objects) {
SetupBuiltinsInternal(isolate);
}
return;
#endif
DCHECK(create_heap_objects);
SetupBuiltinsInternal(isolate);
}
void SetupIsolateDelegate::SetupInterpreter(
interpreter::Interpreter* interpreter, bool create_heap_objects) {
#ifdef V8_GYP_BUILD
// Compatibility hack to keep the deprecated GYP build working.
if (create_heap_objects) {
interpreter::SetupInterpreter::InstallBytecodeHandlers(interpreter);
}
return;
#endif
DCHECK(create_heap_objects);
interpreter::SetupInterpreter::InstallBytecodeHandlers(interpreter);
}
} // namespace internal
} // namespace v8

44
src/setup-isolate.h Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2017 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.
namespace v8 {
namespace internal {
class Builtins;
class Code;
class Isolate;
namespace interpreter {
class Interpreter;
} // namespace interpreter
// This class is an abstraction layer around initialization of components
// that are either deserialized from the snapshot or generated from scratch.
// Currently this includes builtins and interpreter bytecode handlers.
// There are three implementations to choose from (at link time):
// - setup-isolate-deserialize.cc: always loads things from snapshot.
// - setup-isolate-full.cc: always generates things.
// - setup-isolate-for-tests.cc: does the one or the other, controlled by
// the |create_heap_objects| flag.
//
// The actual implementations of generation of builtins and handlers is in
// setup-builtins-internal.cc and setup-interpreter-internal.cc, and is
// linked in by the latter two Delegate implementations.
class SetupIsolateDelegate {
public:
SetupIsolateDelegate() {}
virtual ~SetupIsolateDelegate() {}
virtual void SetupBuiltins(Isolate* isolate, bool create_heap_objects);
virtual void SetupInterpreter(interpreter::Interpreter* interpreter,
bool create_heap_objects);
protected:
static void SetupBuiltinsInternal(Isolate* isolate);
static void AddBuiltin(Builtins* builtins, int index, Code* code);
};
} // namespace internal
} // namespace v8

View File

@ -492,6 +492,7 @@
'builtins/builtins-boolean.cc',
'builtins/builtins-boolean-gen.cc',
'builtins/builtins-call.cc',
'builtins/builtins-call-gen.cc',
'builtins/builtins-callsite.cc',
'builtins/builtins-constructor-gen.cc',
'builtins/builtins-constructor-gen.h',
@ -516,6 +517,7 @@
'builtins/builtins-internal.cc',
'builtins/builtins-internal-gen.cc',
'builtins/builtins-interpreter.cc',
'builtins/builtins-interpreter-gen.cc',
'builtins/builtins-json.cc',
'builtins/builtins-math.cc',
'builtins/builtins-math-gen.cc',
@ -544,6 +546,7 @@
'builtins/builtins-wasm-gen.cc',
'builtins/builtins.cc',
'builtins/builtins.h',
'builtins/setup-builtins-internal.cc',
'cached-powers.cc',
'cached-powers.h',
'callable.h',
@ -1074,6 +1077,8 @@
'interpreter/interpreter-intrinsics.h',
'interpreter/interpreter-intrinsics-generator.cc',
'interpreter/interpreter-intrinsics-generator.h',
'interpreter/setup-interpreter.h',
'interpreter/setup-interpreter-internal.cc',
'isolate-inl.h',
'isolate.cc',
'isolate.h',
@ -1259,6 +1264,8 @@
'runtime/runtime.h',
'safepoint-table.cc',
'safepoint-table.h',
'setup-isolate.h',
'setup-isolate-full.cc',
'signature.h',
'simulator.h',
'small-pointer-list.h',

View File

@ -102,6 +102,8 @@ v8_executable("cctest") {
"profiler-extension.cc",
"profiler-extension.h",
"scope-test-helper.h",
"setup-isolate-for-tests.cc",
"setup-isolate-for-tests.h",
"test-access-checks.cc",
"test-accessor-assembler.cc",
"test-accessors.cc",
@ -332,6 +334,7 @@ v8_executable("cctest") {
deps = [
":resources",
"../..:v8_builtins_generators",
"../..:v8_libbase",
"../..:v8_libplatform",
"../..:wasm_module_runner",

View File

@ -122,6 +122,8 @@
'profiler-extension.cc',
'profiler-extension.h',
'scope-test-helper.h',
'setup-isolate-for-tests.cc',
'setup-isolate-for-tests.h',
'test-access-checks.cc',
'test-accessor-assembler.cc',
'test-accessors.cc',

View File

@ -197,6 +197,10 @@
'test-api/ExternalWrap': [PASS, SLOW],
'test-api/FastReturnValues*': [PASS, SLOW],
'test-decls/CrossScriptReferences_Simple2': [PASS, SLOW],
# "WithWarmup" means starting from a snapshot, for which nosnap builds lack
# support.
'test-serialize/CustomSnapshotDataBlobWithWarmup': [SKIP],
'test-serialize/SnapshotDataBlobWithWarmup': [SKIP],
}], # 'no_snap == True'
['no_snap == False', {
# FunctionEntryHooks require bootstrapping from scratch.

View File

@ -0,0 +1,27 @@
// Copyright 2017 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/setup-isolate-for-tests.h"
#include "src/interpreter/setup-interpreter.h"
namespace v8 {
namespace internal {
void SetupIsolateDelegateForTests::SetupBuiltins(Isolate* isolate,
bool create_heap_objects) {
if (create_heap_objects) {
SetupBuiltinsInternal(isolate);
}
}
void SetupIsolateDelegateForTests::SetupInterpreter(
interpreter::Interpreter* interpreter, bool create_heap_objects) {
if (create_heap_objects) {
interpreter::SetupInterpreter::InstallBytecodeHandlers(interpreter);
}
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,22 @@
// Copyright 2017 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/setup-isolate.h"
namespace v8 {
namespace internal {
class SetupIsolateDelegateForTests : public SetupIsolateDelegate {
public:
SetupIsolateDelegateForTests() : SetupIsolateDelegate() {}
virtual ~SetupIsolateDelegateForTests() {}
void SetupBuiltins(Isolate* isolate, bool create_heap_objects) override;
void SetupInterpreter(interpreter::Interpreter* interpreter,
bool create_heap_objects) override;
};
} // namespace internal
} // namespace v8

View File

@ -49,6 +49,7 @@
#include "src/snapshot/startup-serializer.h"
#include "test/cctest/cctest.h"
#include "test/cctest/heap/heap-utils.h"
#include "test/cctest/setup-isolate-for-tests.h"
using namespace v8::internal;
@ -64,14 +65,26 @@ class TestIsolate : public Isolate {
public:
static v8::Isolate* NewInitialized(bool enable_serializer) {
i::Isolate* isolate = new TestIsolate(enable_serializer);
isolate->setup_delegate_ = new SetupIsolateDelegateForTests();
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
v8::Isolate::Scope isolate_scope(v8_isolate);
isolate->Init(NULL);
return v8_isolate;
}
// Wraps v8::Isolate::New, but with a TestIsolate under the hood.
// Allows flexibility to bootstrap with or without snapshot even when
// the production Isolate class has one or the other behavior baked in.
static v8::Isolate* New(const v8::Isolate::CreateParams& params) {
i::Isolate* isolate = new TestIsolate(false);
isolate->setup_delegate_ = new SetupIsolateDelegateForTests();
return v8::IsolateNewImpl(isolate, params);
}
explicit TestIsolate(bool enable_serializer) : Isolate(enable_serializer) {
set_array_buffer_allocator(CcTest::array_buffer_allocator());
}
void CreateSetupDelegateForTests() {
setup_delegate_ = new SetupIsolateDelegateForTests();
}
};
static Vector<const byte> WritePayload(const Vector<const byte>& payload) {
@ -125,9 +138,10 @@ v8::Isolate* InitializeFromBlob(Vector<const byte> blob) {
{
SnapshotData snapshot_data(blob);
Deserializer deserializer(&snapshot_data);
Isolate* isolate = new TestIsolate(false);
TestIsolate* isolate = new TestIsolate(false);
v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
v8::Isolate::Scope isolate_scope(v8_isolate);
isolate->CreateSetupDelegateForTests();
isolate->Init(&deserializer);
}
return v8_isolate;
@ -633,7 +647,8 @@ TEST(CustomSnapshotDataBlob1) {
params1.snapshot_blob = &data1;
params1.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate1 = v8::Isolate::New(params1);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate1 = TestIsolate::New(params1);
{
v8::Isolate::Scope i_scope(isolate1);
v8::HandleScope h_scope(isolate1);
@ -660,7 +675,8 @@ TEST(CustomSnapshotDataBlob2) {
v8::Isolate::CreateParams params2;
params2.snapshot_blob = &data2;
params2.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate2 = v8::Isolate::New(params2);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate2 = TestIsolate::New(params2);
{
v8::Isolate::Scope i_scope(isolate2);
v8::HandleScope h_scope(isolate2);
@ -703,7 +719,8 @@ TEST(CustomSnapshotDataBlobOutdatedContextWithOverflow) {
params.snapshot_blob = &data;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope i_scope(isolate);
v8::HandleScope h_scope(isolate);
@ -750,7 +767,8 @@ TEST(CustomSnapshotDataBlobWithLocker) {
v8::Isolate::CreateParams params1;
params1.snapshot_blob = &data1;
params1.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate1 = v8::Isolate::New(params1);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate1 = TestIsolate::New(params1);
{
v8::Locker locker(isolate1);
v8::Isolate::Scope i_scope(isolate1);
@ -782,7 +800,8 @@ TEST(CustomSnapshotDataBlobStackOverflow) {
params.snapshot_blob = &data;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope i_scope(isolate);
v8::HandleScope h_scope(isolate);
@ -822,7 +841,8 @@ TEST(SnapshotDataBlobWithWarmup) {
params.snapshot_blob = &warm;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope i_scope(isolate);
v8::HandleScope h_scope(isolate);
@ -855,7 +875,8 @@ TEST(CustomSnapshotDataBlobWithWarmup) {
params.snapshot_blob = &warm;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope i_scope(isolate);
v8::HandleScope h_scope(isolate);
@ -891,7 +912,8 @@ TEST(CustomSnapshotDataBlobImmortalImmovableRoots) {
params.snapshot_blob = &data;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope i_scope(isolate);
v8::HandleScope h_scope(isolate);
@ -1906,7 +1928,8 @@ TEST(SnapshotCreatorMultipleContexts) {
v8::Isolate::CreateParams params;
params.snapshot_blob = &blob;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope isolate_scope(isolate);
{
@ -2028,7 +2051,8 @@ TEST(SnapshotCreatorExternalReferences) {
params.snapshot_blob = &blob;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
params.external_references = original_external_references;
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
@ -2045,7 +2069,8 @@ TEST(SnapshotCreatorExternalReferences) {
params.snapshot_blob = &blob;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
params.external_references = replaced_external_references;
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
@ -2178,7 +2203,8 @@ TEST(SnapshotCreatorTemplates) {
params.snapshot_blob = &blob;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
params.external_references = original_external_references;
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope isolate_scope(isolate);
{
@ -2355,7 +2381,8 @@ TEST(SnapshotCreatorIncludeGlobalProxy) {
params.snapshot_blob = &blob;
params.array_buffer_allocator = CcTest::array_buffer_allocator();
params.external_references = original_external_references;
v8::Isolate* isolate = v8::Isolate::New(params);
// Test-appropriate equivalent of v8::Isolate::New.
v8::Isolate* isolate = TestIsolate::New(params);
{
v8::Isolate::Scope isolate_scope(isolate);
// We can introduce new extensions, which could override the already

View File

@ -185,7 +185,7 @@ v8_executable("unittests") {
#}],
deps = [
"../..:v8",
"../..:v8_builtins_generators",
"../..:v8_libbase",
"../..:v8_libplatform",
"//build/config/sanitizers:deps",
@ -198,6 +198,17 @@ v8_executable("unittests") {
deps += [ "//third_party/icu" ]
}
defines = []
if (is_component_build) {
# unittests can't be built against a shared library, so we
# need to depend on the underlying static target in that case.
deps += [ "../..:v8_maybe_snapshot" ]
defines += [ "BUILDING_V8_SHARED" ]
} else {
deps += [ "../..:v8" ]
}
if (is_win) {
# This warning is benignly triggered by the U16 and U32 macros in
# bytecode-utils.h.

View File

@ -53,6 +53,7 @@ ALL_GYP_PREFIXES = [
GYP_UNSUPPORTED_FEATURES = [
'gcmole',
'setup-isolate-deserialize.cc',
]
GN_FILES = [