Revert "[builtins] Embed builtins into the binary"
This reverts commit 491d5a81dd
.
Reason for revert: https://build.chromium.org/p/client.v8/builders/V8%20Mac64/builds/20696
Original change's description:
> [builtins] Embed builtins into the binary
>
> This embeds code for off-heap-safe builtins into the binary. Actual
> execution of embedded code is not implemented yet.
>
> The embedded file has the following format:
>
> namespace v8 {
> namespace internal {
>
> namespace {
>
> V8_EMBEDDED_TEXT_HEADER(v8_embedded_blob_)
> __asm__( /* builtin offsets and lengths */ );
> __asm__(V8_ASM_LABEL("Builtins_RecordWrite"));
> __asm__( /* binary instruction stream */ );
> /* Repeat for other builtins. */
>
> extern "C" const uint8_t v8_embedded_blob_[];
> static const uint32_t v8_embedded_blob_size_ = /* size in bytes */;
>
> } // namespace
>
> const uint8_t* DefaultEmbeddedBlob() { return v8_embedded_blob_; }
> uint32_t DefaultEmbeddedBlobSize() { return v8_embedded_blob_size_; }
>
> } // namespace internal
> } // namespace v8
>
> Bug: v8:6666
> Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng;luci.v8.try:v8_linux64_fyi_rel_ng
> Change-Id: Ic989f01da69ebe2863f31d934bfbe2c5d6e80864
> Reviewed-on: https://chromium-review.googlesource.com/946011
> Commit-Queue: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#51759}
TBR=yangguo@chromium.org,jgruber@chromium.org
Change-Id: I36f5ee173fca565327b7f3e0ea20503ceef451fe
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:6666
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng;luci.v8.try:v8_linux64_fyi_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/950982
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51760}
This commit is contained in:
parent
491d5a81dd
commit
4f18484b8b
13
BUILD.gn
13
BUILD.gn
@ -817,7 +817,6 @@ if (v8_use_snapshot) {
|
|||||||
sources = []
|
sources = []
|
||||||
|
|
||||||
outputs = [
|
outputs = [
|
||||||
"$target_gen_dir/embedded.cc",
|
|
||||||
"$target_gen_dir/snapshot.cc",
|
"$target_gen_dir/snapshot.cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -828,8 +827,6 @@ if (v8_use_snapshot) {
|
|||||||
"--turbo_instruction_scheduling",
|
"--turbo_instruction_scheduling",
|
||||||
"--startup_src",
|
"--startup_src",
|
||||||
rebase_path("$target_gen_dir/snapshot.cc", root_build_dir),
|
rebase_path("$target_gen_dir/snapshot.cc", root_build_dir),
|
||||||
"--embedded_src",
|
|
||||||
rebase_path("$target_gen_dir/embedded.cc", root_build_dir),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if (v8_random_seed != "0") {
|
if (v8_random_seed != "0") {
|
||||||
@ -943,7 +940,6 @@ v8_source_set("v8_nosnapshot") {
|
|||||||
"$target_gen_dir/experimental-extras-libraries.cc",
|
"$target_gen_dir/experimental-extras-libraries.cc",
|
||||||
"$target_gen_dir/extras-libraries.cc",
|
"$target_gen_dir/extras-libraries.cc",
|
||||||
"$target_gen_dir/libraries.cc",
|
"$target_gen_dir/libraries.cc",
|
||||||
"src/snapshot/embedded-empty.cc",
|
|
||||||
"src/snapshot/snapshot-empty.cc",
|
"src/snapshot/snapshot-empty.cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -988,10 +984,6 @@ if (v8_use_snapshot) {
|
|||||||
"src/setup-isolate-deserialize.cc",
|
"src/setup-isolate-deserialize.cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (v8_enable_embedded_builtins) {
|
|
||||||
sources += [ "$target_gen_dir/embedded.cc" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_jumbo_build == true) {
|
if (use_jumbo_build == true) {
|
||||||
jumbo_excluded_sources = [
|
jumbo_excluded_sources = [
|
||||||
# TODO(mostynb@opera.com): don't exclude these http://crbug.com/752428
|
# TODO(mostynb@opera.com): don't exclude these http://crbug.com/752428
|
||||||
@ -1026,10 +1018,6 @@ if (v8_use_external_startup_data) {
|
|||||||
"src/snapshot/snapshot-external.cc",
|
"src/snapshot/snapshot-external.cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (v8_enable_embedded_builtins) {
|
|
||||||
sources += [ "$target_gen_dir/embedded.cc" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
configs = [ ":internal_config" ]
|
configs = [ ":internal_config" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2065,7 +2053,6 @@ v8_source_set("v8_base") {
|
|||||||
"src/snapshot/default-serializer-allocator.h",
|
"src/snapshot/default-serializer-allocator.h",
|
||||||
"src/snapshot/deserializer.cc",
|
"src/snapshot/deserializer.cc",
|
||||||
"src/snapshot/deserializer.h",
|
"src/snapshot/deserializer.h",
|
||||||
"src/snapshot/macros.h",
|
|
||||||
"src/snapshot/natives-common.cc",
|
"src/snapshot/natives-common.cc",
|
||||||
"src/snapshot/natives.h",
|
"src/snapshot/natives.h",
|
||||||
"src/snapshot/object-deserializer.cc",
|
"src/snapshot/object-deserializer.cc",
|
||||||
|
@ -289,6 +289,55 @@ bool Builtins::IsLazy(int index) {
|
|||||||
bool Builtins::IsIsolateIndependent(int index) {
|
bool Builtins::IsIsolateIndependent(int index) {
|
||||||
DCHECK(IsBuiltinId(index));
|
DCHECK(IsBuiltinId(index));
|
||||||
switch (index) {
|
switch (index) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
case kContinueToCodeStubBuiltin:
|
||||||
|
case kContinueToCodeStubBuiltinWithResult:
|
||||||
|
case kContinueToJavaScriptBuiltin:
|
||||||
|
case kContinueToJavaScriptBuiltinWithResult:
|
||||||
|
#else
|
||||||
|
case kAsyncFunctionAwaitFulfill:
|
||||||
|
case kAsyncFunctionAwaitReject:
|
||||||
|
case kAsyncGeneratorAwaitFulfill:
|
||||||
|
case kAsyncGeneratorAwaitReject:
|
||||||
|
case kAsyncGeneratorReturnClosedFulfill:
|
||||||
|
case kAsyncGeneratorReturnClosedReject:
|
||||||
|
case kAsyncGeneratorReturnFulfill:
|
||||||
|
case kAsyncGeneratorYieldFulfill:
|
||||||
|
case kConstructFunction:
|
||||||
|
case kContinueToCodeStubBuiltin:
|
||||||
|
case kContinueToCodeStubBuiltinWithResult:
|
||||||
|
case kContinueToJavaScriptBuiltin:
|
||||||
|
case kContinueToJavaScriptBuiltinWithResult:
|
||||||
|
case kKeyedLoadICTrampoline:
|
||||||
|
case kKeyedStoreICTrampoline:
|
||||||
|
case kLoadGlobalICInsideTypeofTrampoline:
|
||||||
|
case kLoadGlobalICTrampoline:
|
||||||
|
case kLoadIC_StringLength:
|
||||||
|
case kLoadIC_StringWrapperLength:
|
||||||
|
case kLoadICTrampoline:
|
||||||
|
case kOrderedHashTableHealIndex:
|
||||||
|
case kPromiseFulfillReactionJob:
|
||||||
|
case kStoreGlobalICTrampoline:
|
||||||
|
case kStoreICTrampoline:
|
||||||
|
case kStringRepeat:
|
||||||
|
case kTypeof:
|
||||||
|
case kWeakMapLookupHashIndex:
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool Builtins::IsOffHeapSafe(int index) {
|
||||||
|
#ifndef V8_EMBEDDED_BUILTINS
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
DCHECK(IsBuiltinId(index));
|
||||||
|
if (IsTooShortForOffHeapTrampoline(index)) return false;
|
||||||
|
switch (index) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
case kAbortJS:
|
case kAbortJS:
|
||||||
case kContinueToCodeStubBuiltin:
|
case kContinueToCodeStubBuiltin:
|
||||||
@ -300,15 +349,15 @@ bool Builtins::IsIsolateIndependent(int index) {
|
|||||||
case kLoadGlobalIC_Slow:
|
case kLoadGlobalIC_Slow:
|
||||||
case kLoadIC_Slow:
|
case kLoadIC_Slow:
|
||||||
case kStoreGlobalIC_Slow:
|
case kStoreGlobalIC_Slow:
|
||||||
case kWasmStackGuard:
|
|
||||||
case kThrowWasmTrapUnreachable:
|
|
||||||
case kThrowWasmTrapMemOutOfBounds:
|
|
||||||
case kThrowWasmTrapDivByZero:
|
case kThrowWasmTrapDivByZero:
|
||||||
case kThrowWasmTrapDivUnrepresentable:
|
case kThrowWasmTrapDivUnrepresentable:
|
||||||
case kThrowWasmTrapRemByZero:
|
|
||||||
case kThrowWasmTrapFloatUnrepresentable:
|
case kThrowWasmTrapFloatUnrepresentable:
|
||||||
case kThrowWasmTrapFuncInvalid:
|
case kThrowWasmTrapFuncInvalid:
|
||||||
case kThrowWasmTrapFuncSigMismatch:
|
case kThrowWasmTrapFuncSigMismatch:
|
||||||
|
case kThrowWasmTrapMemOutOfBounds:
|
||||||
|
case kThrowWasmTrapRemByZero:
|
||||||
|
case kThrowWasmTrapUnreachable:
|
||||||
|
case kWasmStackGuard:
|
||||||
#else
|
#else
|
||||||
case kAbortJS:
|
case kAbortJS:
|
||||||
case kAdd:
|
case kAdd:
|
||||||
@ -447,8 +496,6 @@ bool Builtins::IsIsolateIndependent(int index) {
|
|||||||
case kLoadIC_FunctionPrototype:
|
case kLoadIC_FunctionPrototype:
|
||||||
case kLoadIC_Noninlined:
|
case kLoadIC_Noninlined:
|
||||||
case kLoadIC_Slow:
|
case kLoadIC_Slow:
|
||||||
case kLoadIC_StringLength:
|
|
||||||
case kLoadIC_StringWrapperLength:
|
|
||||||
case kLoadICTrampoline:
|
case kLoadICTrampoline:
|
||||||
case kLoadIC_Uninitialized:
|
case kLoadIC_Uninitialized:
|
||||||
case kMapPrototypeEntries:
|
case kMapPrototypeEntries:
|
||||||
@ -458,14 +505,34 @@ bool Builtins::IsIsolateIndependent(int index) {
|
|||||||
case kMapPrototypeHas:
|
case kMapPrototypeHas:
|
||||||
case kMapPrototypeKeys:
|
case kMapPrototypeKeys:
|
||||||
case kMapPrototypeValues:
|
case kMapPrototypeValues:
|
||||||
|
case kMathAcos:
|
||||||
|
case kMathAcosh:
|
||||||
|
case kMathAsin:
|
||||||
|
case kMathAsinh:
|
||||||
|
case kMathAtan:
|
||||||
|
case kMathAtan2:
|
||||||
|
case kMathAtanh:
|
||||||
|
case kMathCbrt:
|
||||||
case kMathCeil:
|
case kMathCeil:
|
||||||
|
case kMathCos:
|
||||||
|
case kMathCosh:
|
||||||
|
case kMathExp:
|
||||||
|
case kMathExpm1:
|
||||||
case kMathFloor:
|
case kMathFloor:
|
||||||
case kMathFround:
|
case kMathFround:
|
||||||
|
case kMathLog:
|
||||||
|
case kMathLog10:
|
||||||
|
case kMathLog1p:
|
||||||
|
case kMathLog2:
|
||||||
case kMathMax:
|
case kMathMax:
|
||||||
case kMathMin:
|
case kMathMin:
|
||||||
case kMathRound:
|
case kMathRound:
|
||||||
case kMathSign:
|
case kMathSign:
|
||||||
|
case kMathSin:
|
||||||
|
case kMathSinh:
|
||||||
case kMathSqrt:
|
case kMathSqrt:
|
||||||
|
case kMathTan:
|
||||||
|
case kMathTanh:
|
||||||
case kMathTrunc:
|
case kMathTrunc:
|
||||||
case kModulus:
|
case kModulus:
|
||||||
case kMultiply:
|
case kMultiply:
|
||||||
@ -644,16 +711,6 @@ bool Builtins::IsIsolateIndependent(int index) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
bool Builtins::IsOffHeapSafe(int index) {
|
|
||||||
#ifndef V8_EMBEDDED_BUILTINS
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
DCHECK(IsBuiltinId(index));
|
|
||||||
if (IsTooShortForOffHeapTrampoline(index)) return false;
|
|
||||||
return IsIsolateIndependent(index);
|
|
||||||
#endif // V8_EMBEDDED_BUILTINS
|
#endif // V8_EMBEDDED_BUILTINS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,8 +1067,6 @@ DEFINE_STRING(testing_string_flag, "Hello, world!", "string-flag")
|
|||||||
DEFINE_INT(testing_prng_seed, 42, "Seed used for threading test randomness")
|
DEFINE_INT(testing_prng_seed, 42, "Seed used for threading test randomness")
|
||||||
|
|
||||||
// mksnapshot.cc
|
// mksnapshot.cc
|
||||||
DEFINE_STRING(embedded_src, nullptr,
|
|
||||||
"Path for the generated embedded data file. (mksnapshot only)")
|
|
||||||
DEFINE_STRING(startup_src, nullptr,
|
DEFINE_STRING(startup_src, nullptr,
|
||||||
"Write V8 startup as C++ src. (mksnapshot only)")
|
"Write V8 startup as C++ src. (mksnapshot only)")
|
||||||
DEFINE_STRING(startup_blob, nullptr,
|
DEFINE_STRING(startup_blob, nullptr,
|
||||||
|
@ -68,17 +68,6 @@ namespace internal {
|
|||||||
|
|
||||||
base::Atomic32 ThreadId::highest_thread_id_ = 0;
|
base::Atomic32 ThreadId::highest_thread_id_ = 0;
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
extern const uint8_t* DefaultEmbeddedBlob();
|
|
||||||
extern uint32_t DefaultEmbeddedBlobSize();
|
|
||||||
|
|
||||||
const uint8_t* Isolate::embedded_blob() const { return DefaultEmbeddedBlob(); }
|
|
||||||
|
|
||||||
uint32_t Isolate::embedded_blob_size() const {
|
|
||||||
return DefaultEmbeddedBlobSize();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int ThreadId::AllocateThreadId() {
|
int ThreadId::AllocateThreadId() {
|
||||||
int new_id = base::Relaxed_AtomicIncrement(&highest_thread_id_, 1);
|
int new_id = base::Relaxed_AtomicIncrement(&highest_thread_id_, 1);
|
||||||
return new_id;
|
return new_id;
|
||||||
@ -2832,11 +2821,45 @@ void PrintBuiltinSizes(Isolate* isolate) {
|
|||||||
const char* name = builtins->name(i);
|
const char* name = builtins->name(i);
|
||||||
const char* kind = Builtins::KindNameOf(i);
|
const char* kind = Builtins::KindNameOf(i);
|
||||||
Code* code = builtins->builtin(i);
|
Code* code = builtins->builtin(i);
|
||||||
PrintF(stdout, "%s Builtin, %s, %d\n", kind, name, code->InstructionSize());
|
PrintF(stdout, "%s Builtin, %s, %d\n", kind, name,
|
||||||
|
code->instruction_size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
#ifdef V8_EMBEDDED_BUILTINS
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool BuiltinAliasesOffHeapTrampolineRegister(Isolate* isolate,
|
||||||
|
int builtin_index) {
|
||||||
|
switch (Builtins::KindOf(builtin_index)) {
|
||||||
|
case Builtins::CPP:
|
||||||
|
case Builtins::TFC:
|
||||||
|
case Builtins::TFH:
|
||||||
|
case Builtins::TFJ:
|
||||||
|
case Builtins::TFS:
|
||||||
|
break;
|
||||||
|
case Builtins::API:
|
||||||
|
case Builtins::ASM:
|
||||||
|
// TODO(jgruber): Extend checks to remaining kinds.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Callable callable = Builtins::CallableFor(
|
||||||
|
isolate, static_cast<Builtins::Name>(builtin_index));
|
||||||
|
CallInterfaceDescriptor descriptor = callable.descriptor();
|
||||||
|
|
||||||
|
if (descriptor.ContextRegister() == kOffHeapTrampolineRegister) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < descriptor.GetRegisterParameterCount(); i++) {
|
||||||
|
Register reg = descriptor.GetRegisterParameter(i);
|
||||||
|
if (reg == kOffHeapTrampolineRegister) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ChangeToOffHeapTrampoline(Isolate* isolate, Handle<Code> code,
|
void ChangeToOffHeapTrampoline(Isolate* isolate, Handle<Code> code,
|
||||||
InstructionStream* stream) {
|
InstructionStream* stream) {
|
||||||
DCHECK(Builtins::IsOffHeapSafe(code->builtin_index()));
|
DCHECK(Builtins::IsOffHeapSafe(code->builtin_index()));
|
||||||
@ -2847,6 +2870,8 @@ void ChangeToOffHeapTrampoline(Isolate* isolate, Handle<Code> code,
|
|||||||
|
|
||||||
// Generate replacement code that simply tail-calls the off-heap code.
|
// Generate replacement code that simply tail-calls the off-heap code.
|
||||||
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
|
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
|
||||||
|
DCHECK(
|
||||||
|
!BuiltinAliasesOffHeapTrampolineRegister(isolate, code->builtin_index()));
|
||||||
DCHECK(!masm.has_frame());
|
DCHECK(!masm.has_frame());
|
||||||
{
|
{
|
||||||
FrameScope scope(&masm, StackFrame::NONE);
|
FrameScope scope(&masm, StackFrame::NONE);
|
||||||
|
@ -1249,9 +1249,6 @@ class Isolate {
|
|||||||
BuiltinsConstantsTableBuilder* builtins_constants_table_builder() const {
|
BuiltinsConstantsTableBuilder* builtins_constants_table_builder() const {
|
||||||
return builtins_constants_table_builder_;
|
return builtins_constants_table_builder_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* embedded_blob() const;
|
|
||||||
uint32_t embedded_blob_size() const;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) {
|
void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) {
|
||||||
|
@ -13980,7 +13980,6 @@ SafepointEntry Code::GetSafepointEntry(Address pc) {
|
|||||||
return table.FindEntry(pc);
|
return table.FindEntry(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
int Code::OffHeapInstructionSize() {
|
int Code::OffHeapInstructionSize() {
|
||||||
DCHECK(Builtins::IsOffHeapBuiltin(this));
|
DCHECK(Builtins::IsOffHeapBuiltin(this));
|
||||||
InstructionStream* stream =
|
InstructionStream* stream =
|
||||||
@ -14001,7 +14000,6 @@ Address Code::OffHeapInstructionEnd() {
|
|||||||
InstructionStream::TryLookupInstructionStream(GetIsolate(), this);
|
InstructionStream::TryLookupInstructionStream(GetIsolate(), this);
|
||||||
return stream->bytes() + stream->byte_length();
|
return stream->bytes() + stream->byte_length();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template <typename Code>
|
template <typename Code>
|
||||||
@ -14138,36 +14136,6 @@ const char* AbstractCode::Kind2String(Kind kind) {
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
bool Code::IsProcessIndependent() {
|
|
||||||
constexpr int all_real_modes_mask =
|
|
||||||
(1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - 1;
|
|
||||||
constexpr int mode_mask =
|
|
||||||
all_real_modes_mask & ~RelocInfo::ModeMask(RelocInfo::COMMENT) &
|
|
||||||
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) &
|
|
||||||
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) &
|
|
||||||
~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
|
|
||||||
~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
|
|
||||||
STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);
|
|
||||||
STATIC_ASSERT(RelocInfo::ModeMask(RelocInfo::COMMENT) ==
|
|
||||||
(1 << RelocInfo::COMMENT));
|
|
||||||
STATIC_ASSERT(
|
|
||||||
mode_mask ==
|
|
||||||
(RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::WASM_CONTEXT_REFERENCE) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_HANDLE) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
|
|
||||||
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE)));
|
|
||||||
|
|
||||||
RelocIterator it(this, mode_mask);
|
|
||||||
return it.done();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
|
Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
|
||||||
DCHECK(code->kind() == OPTIMIZED_FUNCTION);
|
DCHECK(code->kind() == OPTIMIZED_FUNCTION);
|
||||||
WeakCell* raw_cell = code->CachedWeakCell();
|
WeakCell* raw_cell = code->CachedWeakCell();
|
||||||
|
@ -64,9 +64,7 @@ class Code : public HeapObject {
|
|||||||
// off-heap instruction stream rather than the on-heap trampoline located
|
// off-heap instruction stream rather than the on-heap trampoline located
|
||||||
// at instruction_start.
|
// at instruction_start.
|
||||||
inline int InstructionSize();
|
inline int InstructionSize();
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
int OffHeapInstructionSize();
|
int OffHeapInstructionSize();
|
||||||
#endif
|
|
||||||
|
|
||||||
// [relocation_info]: Code relocation information
|
// [relocation_info]: Code relocation information
|
||||||
DECL_ACCESSORS(relocation_info, ByteArray)
|
DECL_ACCESSORS(relocation_info, ByteArray)
|
||||||
@ -229,9 +227,7 @@ class Code : public HeapObject {
|
|||||||
// this differs from instruction_start (which would point to the off-heap
|
// this differs from instruction_start (which would point to the off-heap
|
||||||
// trampoline instead).
|
// trampoline instead).
|
||||||
inline Address InstructionStart();
|
inline Address InstructionStart();
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
Address OffHeapInstructionStart();
|
Address OffHeapInstructionStart();
|
||||||
#endif
|
|
||||||
|
|
||||||
// Returns the address right after the last instruction.
|
// Returns the address right after the last instruction.
|
||||||
inline byte* instruction_end() const;
|
inline byte* instruction_end() const;
|
||||||
@ -240,9 +236,7 @@ class Code : public HeapObject {
|
|||||||
// objects this differs from instruction_end (which would point to the
|
// objects this differs from instruction_end (which would point to the
|
||||||
// off-heap trampoline instead).
|
// off-heap trampoline instead).
|
||||||
inline Address InstructionEnd();
|
inline Address InstructionEnd();
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
Address OffHeapInstructionEnd();
|
Address OffHeapInstructionEnd();
|
||||||
#endif
|
|
||||||
|
|
||||||
// Returns the size of the instructions, padding, relocation and unwinding
|
// Returns the size of the instructions, padding, relocation and unwinding
|
||||||
// information.
|
// information.
|
||||||
@ -342,10 +336,6 @@ class Code : public HeapObject {
|
|||||||
void VerifyEmbeddedObjects(VerifyMode mode = kNoContextRetainingPointers);
|
void VerifyEmbeddedObjects(VerifyMode mode = kNoContextRetainingPointers);
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
bool IsProcessIndependent();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline bool CanContainWeakObjects();
|
inline bool CanContainWeakObjects();
|
||||||
|
|
||||||
inline bool IsWeakObject(Object* object);
|
inline bool IsWeakObject(Object* object);
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
// Copyright 2018 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.
|
|
||||||
|
|
||||||
// Used for building without embedded data.
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace v8 {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
const uint8_t* DefaultEmbeddedBlob() { return nullptr; }
|
|
||||||
uint32_t DefaultEmbeddedBlobSize() { return 0; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace v8
|
|
@ -1,42 +0,0 @@
|
|||||||
// Copyright 2018 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_SNAPSHOT_MACROS_H_
|
|
||||||
#define V8_SNAPSHOT_MACROS_H_
|
|
||||||
|
|
||||||
// .byte portability macros.
|
|
||||||
|
|
||||||
#if defined(V8_OS_MACOSX) // MACOSX
|
|
||||||
#define V8_ASM_MANGLE_LABEL "_"
|
|
||||||
#define V8_ASM_RODATA_SECTION ".const_data\n"
|
|
||||||
#define V8_ASM_TEXT_SECTION ".text\n"
|
|
||||||
#define V8_ASM_GLOBAL(NAME) ".globl " V8_ASM_MANGLE_LABEL NAME "\n"
|
|
||||||
#elif defined(V8_OS_WIN) // WIN
|
|
||||||
#if defined(V8_TARGET_ARCH_X64)
|
|
||||||
#define V8_ASM_MANGLE_LABEL ""
|
|
||||||
#else
|
|
||||||
#define V8_ASM_MANGLE_LABEL "_"
|
|
||||||
#endif
|
|
||||||
#define V8_ASM_RODATA_SECTION ".section .rodata\n"
|
|
||||||
#define V8_ASM_TEXT_SECTION ".section .text\n"
|
|
||||||
#define V8_ASM_GLOBAL(NAME) ".global " V8_ASM_MANGLE_LABEL NAME "\n"
|
|
||||||
#else // !MACOSX && !WIN
|
|
||||||
#define V8_ASM_MANGLE_LABEL ""
|
|
||||||
#define V8_ASM_RODATA_SECTION ".section .rodata\n"
|
|
||||||
#define V8_ASM_TEXT_SECTION ".section .text\n"
|
|
||||||
#define V8_ASM_GLOBAL(NAME) ".global " V8_ASM_MANGLE_LABEL NAME "\n"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define V8_ASM_BALIGN16 ".balign 16\n"
|
|
||||||
#define V8_ASM_LABEL(NAME) V8_ASM_MANGLE_LABEL NAME ":\n"
|
|
||||||
|
|
||||||
#define V8_EMBEDDED_TEXT_HEADER(LABEL) \
|
|
||||||
__asm__(V8_ASM_TEXT_SECTION V8_ASM_GLOBAL(#LABEL) \
|
|
||||||
V8_ASM_BALIGN16 V8_ASM_LABEL(#LABEL));
|
|
||||||
|
|
||||||
#define V8_EMBEDDED_RODATA_HEADER(LABEL) \
|
|
||||||
__asm__(V8_ASM_RODATA_SECTION V8_ASM_GLOBAL(#LABEL) \
|
|
||||||
V8_ASM_BALIGN16 V8_ASM_LABEL(#LABEL));
|
|
||||||
|
|
||||||
#endif // V8_SNAPSHOT_MACROS_H_
|
|
@ -13,7 +13,6 @@
|
|||||||
#include "src/msan.h"
|
#include "src/msan.h"
|
||||||
#include "src/snapshot/natives.h"
|
#include "src/snapshot/natives.h"
|
||||||
#include "src/snapshot/partial-serializer.h"
|
#include "src/snapshot/partial-serializer.h"
|
||||||
#include "src/snapshot/snapshot.h"
|
|
||||||
#include "src/snapshot/startup-serializer.h"
|
#include "src/snapshot/startup-serializer.h"
|
||||||
|
|
||||||
class SnapshotWriter {
|
class SnapshotWriter {
|
||||||
@ -21,12 +20,6 @@ class SnapshotWriter {
|
|||||||
SnapshotWriter()
|
SnapshotWriter()
|
||||||
: snapshot_cpp_path_(nullptr), snapshot_blob_path_(nullptr) {}
|
: snapshot_cpp_path_(nullptr), snapshot_blob_path_(nullptr) {}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
void SetEmbeddedFile(const char* embedded_cpp_file) {
|
|
||||||
embedded_cpp_path_ = embedded_cpp_file;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SetSnapshotFile(const char* snapshot_cpp_file) {
|
void SetSnapshotFile(const char* snapshot_cpp_file) {
|
||||||
snapshot_cpp_path_ = snapshot_cpp_file;
|
snapshot_cpp_path_ = snapshot_cpp_file;
|
||||||
}
|
}
|
||||||
@ -46,12 +39,6 @@ class SnapshotWriter {
|
|||||||
MaybeWriteStartupBlob(blob_vector);
|
MaybeWriteStartupBlob(blob_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
void WriteEmbedded(const i::EmbeddedData* blob) const {
|
|
||||||
MaybeWriteEmbeddedFile(blob);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void MaybeWriteStartupBlob(const i::Vector<const i::byte>& blob) const {
|
void MaybeWriteStartupBlob(const i::Vector<const i::byte>& blob) const {
|
||||||
if (!snapshot_blob_path_) return;
|
if (!snapshot_blob_path_) return;
|
||||||
@ -71,14 +58,14 @@ class SnapshotWriter {
|
|||||||
|
|
||||||
FILE* fp = GetFileDescriptorOrDie(snapshot_cpp_path_);
|
FILE* fp = GetFileDescriptorOrDie(snapshot_cpp_path_);
|
||||||
|
|
||||||
WriteSnapshotFilePrefix(fp);
|
WriteFilePrefix(fp);
|
||||||
WriteSnapshotFileData(fp, blob);
|
WriteData(fp, blob);
|
||||||
WriteSnapshotFileSuffix(fp);
|
WriteFileSuffix(fp);
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteSnapshotFilePrefix(FILE* fp) {
|
static void WriteFilePrefix(FILE* fp) {
|
||||||
fprintf(fp, "// Autogenerated snapshot file. Do not edit.\n\n");
|
fprintf(fp, "// Autogenerated snapshot file. Do not edit.\n\n");
|
||||||
fprintf(fp, "#include \"src/v8.h\"\n");
|
fprintf(fp, "#include \"src/v8.h\"\n");
|
||||||
fprintf(fp, "#include \"src/base/platform/platform.h\"\n\n");
|
fprintf(fp, "#include \"src/base/platform/platform.h\"\n\n");
|
||||||
@ -87,7 +74,7 @@ class SnapshotWriter {
|
|||||||
fprintf(fp, "namespace internal {\n\n");
|
fprintf(fp, "namespace internal {\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteSnapshotFileSuffix(FILE* fp) {
|
static void WriteFileSuffix(FILE* fp) {
|
||||||
fprintf(fp, "const v8::StartupData* Snapshot::DefaultSnapshotBlob() {\n");
|
fprintf(fp, "const v8::StartupData* Snapshot::DefaultSnapshotBlob() {\n");
|
||||||
fprintf(fp, " return &blob;\n");
|
fprintf(fp, " return &blob;\n");
|
||||||
fprintf(fp, "}\n\n");
|
fprintf(fp, "}\n\n");
|
||||||
@ -95,18 +82,17 @@ class SnapshotWriter {
|
|||||||
fprintf(fp, "} // namespace v8\n");
|
fprintf(fp, "} // namespace v8\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteSnapshotFileData(FILE* fp,
|
static void WriteData(FILE* fp, const i::Vector<const i::byte>& blob) {
|
||||||
const i::Vector<const i::byte>& blob) {
|
|
||||||
fprintf(fp, "static const byte blob_data[] = {\n");
|
fprintf(fp, "static const byte blob_data[] = {\n");
|
||||||
WriteBinaryContentsAsCArray(fp, blob);
|
WriteSnapshotData(fp, blob);
|
||||||
fprintf(fp, "};\n");
|
fprintf(fp, "};\n");
|
||||||
fprintf(fp, "static const int blob_size = %d;\n", blob.length());
|
fprintf(fp, "static const int blob_size = %d;\n", blob.length());
|
||||||
fprintf(fp, "static const v8::StartupData blob =\n");
|
fprintf(fp, "static const v8::StartupData blob =\n");
|
||||||
fprintf(fp, "{ (const char*) blob_data, blob_size };\n");
|
fprintf(fp, "{ (const char*) blob_data, blob_size };\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteBinaryContentsAsCArray(
|
static void WriteSnapshotData(FILE* fp,
|
||||||
FILE* fp, const i::Vector<const i::byte>& blob) {
|
const i::Vector<const i::byte>& blob) {
|
||||||
for (int i = 0; i < blob.length(); i++) {
|
for (int i = 0; i < blob.length(); i++) {
|
||||||
if ((i & 0x1F) == 0x1F) fprintf(fp, "\n");
|
if ((i & 0x1F) == 0x1F) fprintf(fp, "\n");
|
||||||
if (i > 0) fprintf(fp, ",");
|
if (i > 0) fprintf(fp, ",");
|
||||||
@ -115,96 +101,6 @@ class SnapshotWriter {
|
|||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const {
|
|
||||||
if (embedded_cpp_path_ == nullptr) return;
|
|
||||||
|
|
||||||
FILE* fp = GetFileDescriptorOrDie(embedded_cpp_path_);
|
|
||||||
|
|
||||||
WriteEmbeddedFilePrefix(fp);
|
|
||||||
WriteEmbeddedFileData(fp, blob);
|
|
||||||
WriteEmbeddedFileSuffix(fp);
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteEmbeddedFilePrefix(FILE* fp) {
|
|
||||||
fprintf(fp, "// Autogenerated file. Do not edit.\n\n");
|
|
||||||
fprintf(fp, "#include <cstdint>\n\n");
|
|
||||||
fprintf(fp, "#include \"src/snapshot/macros.h\"\n\n");
|
|
||||||
fprintf(fp, "namespace v8 {\n");
|
|
||||||
fprintf(fp, "namespace internal {\n\n");
|
|
||||||
fprintf(fp, "namespace {\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteEmbeddedFileSuffix(FILE* fp) {
|
|
||||||
fprintf(fp, "} // namespace\n\n");
|
|
||||||
fprintf(
|
|
||||||
fp,
|
|
||||||
"const uint8_t* DefaultEmbeddedBlob() { return v8_embedded_blob_; }\n");
|
|
||||||
fprintf(fp,
|
|
||||||
"uint32_t DefaultEmbeddedBlobSize() { return "
|
|
||||||
"v8_embedded_blob_size_; }\n\n");
|
|
||||||
fprintf(fp, "} // namespace internal\n");
|
|
||||||
fprintf(fp, "} // namespace v8\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteEmbeddedFileData(FILE* fp, const i::EmbeddedData* blob) {
|
|
||||||
fprintf(fp, "V8_EMBEDDED_TEXT_HEADER(v8_embedded_blob_)\n");
|
|
||||||
WriteBinaryContentsAsByteDirective(fp, blob->data(),
|
|
||||||
i::EmbeddedData::RawDataOffset());
|
|
||||||
WriteBuiltins(fp, blob);
|
|
||||||
fprintf(fp, "extern \"C\" const uint8_t v8_embedded_blob_[];\n");
|
|
||||||
fprintf(fp, "static const uint32_t v8_embedded_blob_size_ = %d;\n\n",
|
|
||||||
blob->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteBuiltins(FILE* fp, const i::EmbeddedData* blob) {
|
|
||||||
for (int i = 0; i < i::Builtins::builtin_count; i++) {
|
|
||||||
if (!blob->ContainsBuiltin(i)) continue;
|
|
||||||
|
|
||||||
fprintf(fp, "__asm__(V8_ASM_LABEL(\"Builtins_%s\"));\n",
|
|
||||||
i::Builtins::name(i));
|
|
||||||
WriteBinaryContentsAsByteDirective(
|
|
||||||
fp, blob->InstructionStartOfBuiltin(i),
|
|
||||||
blob->PaddedInstructionSizeOfBuiltin(i));
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteBinaryContentsAsByteDirective(FILE* fp, const uint8_t* data,
|
|
||||||
uint32_t size) {
|
|
||||||
static const int kTextWidth = 80;
|
|
||||||
int current_line_length = 0;
|
|
||||||
int printed_chars;
|
|
||||||
|
|
||||||
fprintf(fp, "__asm__(\n");
|
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
|
||||||
if (current_line_length == 0) {
|
|
||||||
printed_chars = fprintf(fp, "%s", " \".byte ");
|
|
||||||
DCHECK_LT(0, printed_chars);
|
|
||||||
current_line_length += printed_chars;
|
|
||||||
} else {
|
|
||||||
printed_chars = fprintf(fp, ",");
|
|
||||||
DCHECK_EQ(1, printed_chars);
|
|
||||||
current_line_length += printed_chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
printed_chars = fprintf(fp, "0x%02x", data[i]);
|
|
||||||
DCHECK_LT(0, printed_chars);
|
|
||||||
current_line_length += printed_chars;
|
|
||||||
|
|
||||||
if (current_line_length + strlen(",0xFF\\n\"") > kTextWidth) {
|
|
||||||
fprintf(fp, "\\n\"\n");
|
|
||||||
current_line_length = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_line_length != 0) fprintf(fp, "\\n\"\n");
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static FILE* GetFileDescriptorOrDie(const char* filename) {
|
static FILE* GetFileDescriptorOrDie(const char* filename) {
|
||||||
FILE* fp = v8::base::OS::FOpen(filename, "wb");
|
FILE* fp = v8::base::OS::FOpen(filename, "wb");
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
@ -214,9 +110,6 @@ class SnapshotWriter {
|
|||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
const char* embedded_cpp_path_ = nullptr;
|
|
||||||
#endif
|
|
||||||
const char* snapshot_cpp_path_;
|
const char* snapshot_cpp_path_;
|
||||||
const char* snapshot_blob_path_;
|
const char* snapshot_blob_path_;
|
||||||
};
|
};
|
||||||
@ -246,64 +139,6 @@ char* GetExtraCode(char* filename, const char* description) {
|
|||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context,
|
|
||||||
const char* utf8_source, const char* name) {
|
|
||||||
v8::base::ElapsedTimer timer;
|
|
||||||
timer.Start();
|
|
||||||
v8::Context::Scope context_scope(context);
|
|
||||||
v8::TryCatch try_catch(isolate);
|
|
||||||
v8::Local<v8::String> source_string;
|
|
||||||
if (!v8::String::NewFromUtf8(isolate, utf8_source, v8::NewStringType::kNormal)
|
|
||||||
.ToLocal(&source_string)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
v8::Local<v8::String> resource_name =
|
|
||||||
v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)
|
|
||||||
.ToLocalChecked();
|
|
||||||
v8::ScriptOrigin origin(resource_name);
|
|
||||||
v8::ScriptCompiler::Source source(source_string, origin);
|
|
||||||
v8::Local<v8::Script> script;
|
|
||||||
if (!v8::ScriptCompiler::Compile(context, &source).ToLocal(&script))
|
|
||||||
return false;
|
|
||||||
if (script->Run(context).IsEmpty()) return false;
|
|
||||||
if (i::FLAG_profile_deserialization) {
|
|
||||||
i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name,
|
|
||||||
timer.Elapsed().InMillisecondsF());
|
|
||||||
}
|
|
||||||
timer.Stop();
|
|
||||||
CHECK(!try_catch.HasCaught());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::StartupData CreateSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator,
|
|
||||||
const char* script_source = NULL) {
|
|
||||||
// Create a new isolate and a new context from scratch, optionally run
|
|
||||||
// a script to embed, and serialize to create a snapshot blob.
|
|
||||||
v8::StartupData result = {nullptr, 0};
|
|
||||||
v8::base::ElapsedTimer timer;
|
|
||||||
timer.Start();
|
|
||||||
{
|
|
||||||
v8::Isolate* isolate = snapshot_creator->GetIsolate();
|
|
||||||
{
|
|
||||||
v8::HandleScope scope(isolate);
|
|
||||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
|
||||||
if (script_source != nullptr &&
|
|
||||||
!RunExtraCode(isolate, context, script_source, "<embedded>")) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
snapshot_creator->SetDefaultContext(context);
|
|
||||||
}
|
|
||||||
result = snapshot_creator->CreateBlob(
|
|
||||||
v8::SnapshotCreator::FunctionCodeHandling::kClear);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i::FLAG_profile_deserialization) {
|
|
||||||
i::PrintF("Creating snapshot took %0.3f ms\n",
|
|
||||||
timer.Elapsed().InMillisecondsF());
|
|
||||||
}
|
|
||||||
timer.Stop();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
// Make mksnapshot runs predictable to create reproducible snapshots.
|
// Make mksnapshot runs predictable to create reproducible snapshots.
|
||||||
@ -329,27 +164,11 @@ int main(int argc, char** argv) {
|
|||||||
SnapshotWriter writer;
|
SnapshotWriter writer;
|
||||||
if (i::FLAG_startup_src) writer.SetSnapshotFile(i::FLAG_startup_src);
|
if (i::FLAG_startup_src) writer.SetSnapshotFile(i::FLAG_startup_src);
|
||||||
if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
|
if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
if (i::FLAG_embedded_src) writer.SetEmbeddedFile(i::FLAG_embedded_src);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
v8::StartupData blob;
|
char* embed_script =
|
||||||
{
|
GetExtraCode(argc >= 2 ? argv[1] : nullptr, "embedding");
|
||||||
char* embed_script =
|
v8::StartupData blob = v8::V8::CreateSnapshotDataBlob(embed_script);
|
||||||
GetExtraCode(argc >= 2 ? argv[1] : nullptr, "embedding");
|
delete[] embed_script;
|
||||||
v8::SnapshotCreator snapshot_creator;
|
|
||||||
blob = CreateSnapshotDataBlob(&snapshot_creator, embed_script);
|
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
i::Isolate* isolate =
|
|
||||||
reinterpret_cast<i::Isolate*>(snapshot_creator.GetIsolate());
|
|
||||||
i::EmbeddedData embedded_blob = i::Snapshot::CreateEmbeddedBlob(isolate);
|
|
||||||
writer.WriteEmbedded(&embedded_blob);
|
|
||||||
delete[] embedded_blob.data();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
delete[] embed_script;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* warmup_script =
|
char* warmup_script =
|
||||||
GetExtraCode(argc >= 3 ? argv[2] : nullptr, "warm up");
|
GetExtraCode(argc >= 3 ? argv[2] : nullptr, "warm up");
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#include "src/api.h"
|
#include "src/api.h"
|
||||||
#include "src/base/platform/platform.h"
|
#include "src/base/platform/platform.h"
|
||||||
#include "src/callable.h"
|
|
||||||
#include "src/interface-descriptors.h"
|
|
||||||
#include "src/objects-inl.h"
|
#include "src/objects-inl.h"
|
||||||
#include "src/snapshot/builtin-deserializer.h"
|
#include "src/snapshot/builtin-deserializer.h"
|
||||||
#include "src/snapshot/builtin-serializer.h"
|
#include "src/snapshot/builtin-serializer.h"
|
||||||
@ -266,138 +264,6 @@ v8::StartupData Snapshot::CreateSnapshotBlob(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
#ifdef DEBUG
|
|
||||||
namespace {
|
|
||||||
bool BuiltinAliasesOffHeapTrampolineRegister(Isolate* isolate, Code* code) {
|
|
||||||
DCHECK(Builtins::IsOffHeapSafe(code->builtin_index()));
|
|
||||||
switch (Builtins::KindOf(code->builtin_index())) {
|
|
||||||
case Builtins::CPP:
|
|
||||||
case Builtins::TFC:
|
|
||||||
case Builtins::TFH:
|
|
||||||
case Builtins::TFJ:
|
|
||||||
case Builtins::TFS:
|
|
||||||
break;
|
|
||||||
case Builtins::API:
|
|
||||||
case Builtins::ASM:
|
|
||||||
// TODO(jgruber): Extend checks to remaining kinds.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Callable callable = Builtins::CallableFor(
|
|
||||||
isolate, static_cast<Builtins::Name>(code->builtin_index()));
|
|
||||||
CallInterfaceDescriptor descriptor = callable.descriptor();
|
|
||||||
|
|
||||||
if (descriptor.ContextRegister() == kOffHeapTrampolineRegister) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < descriptor.GetRegisterParameterCount(); i++) {
|
|
||||||
Register reg = descriptor.GetRegisterParameter(i);
|
|
||||||
if (reg == kOffHeapTrampolineRegister) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
// static
|
|
||||||
EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) {
|
|
||||||
Builtins* builtins = isolate->builtins();
|
|
||||||
|
|
||||||
// Builtins must be deserialized to be copied off-heap.
|
|
||||||
Snapshot::EnsureAllBuiltinsAreDeserialized(isolate);
|
|
||||||
|
|
||||||
// Store instruction stream lengths and offsets.
|
|
||||||
std::vector<uint32_t> lengths(kTableSize);
|
|
||||||
std::vector<uint32_t> offsets(kTableSize);
|
|
||||||
|
|
||||||
bool saw_unsafe_builtin = false;
|
|
||||||
uint32_t raw_data_size = 0;
|
|
||||||
for (int i = 0; i < Builtins::builtin_count; i++) {
|
|
||||||
Code* code = builtins->builtin(i);
|
|
||||||
|
|
||||||
if (Builtins::IsOffHeapSafe(i)) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Sanity-check that the given builtin is process-independent and does not
|
|
||||||
// use the trampoline register in its calling convention.
|
|
||||||
if (!code->IsProcessIndependent()) {
|
|
||||||
saw_unsafe_builtin = true;
|
|
||||||
fprintf(stderr, "%s is not process-independent.\n", Builtins::name(i));
|
|
||||||
}
|
|
||||||
if (BuiltinAliasesOffHeapTrampolineRegister(isolate, code)) {
|
|
||||||
saw_unsafe_builtin = true;
|
|
||||||
fprintf(stderr, "%s aliases the off-heap trampoline register.\n",
|
|
||||||
Builtins::name(i));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t length = static_cast<uint32_t>(code->instruction_size());
|
|
||||||
|
|
||||||
DCHECK_EQ(0, raw_data_size % kCodeAlignment);
|
|
||||||
offsets[i] = raw_data_size;
|
|
||||||
lengths[i] = length;
|
|
||||||
|
|
||||||
// Align the start of each instruction stream.
|
|
||||||
raw_data_size += RoundUp<kCodeAlignment>(length);
|
|
||||||
} else {
|
|
||||||
offsets[i] = raw_data_size;
|
|
||||||
lengths[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CHECK(!saw_unsafe_builtin);
|
|
||||||
|
|
||||||
const uint32_t blob_size = RawDataOffset() + raw_data_size;
|
|
||||||
uint8_t* blob = new uint8_t[blob_size];
|
|
||||||
std::memset(blob, 0, blob_size);
|
|
||||||
|
|
||||||
// Write the offsets and length tables.
|
|
||||||
DCHECK_EQ(OffsetsSize(), sizeof(offsets[0]) * offsets.size());
|
|
||||||
std::memcpy(blob + OffsetsOffset(), offsets.data(), OffsetsSize());
|
|
||||||
|
|
||||||
DCHECK_EQ(LengthsSize(), sizeof(lengths[0]) * lengths.size());
|
|
||||||
std::memcpy(blob + LengthsOffset(), lengths.data(), LengthsSize());
|
|
||||||
|
|
||||||
// Write the raw data section.
|
|
||||||
for (int i = 0; i < Builtins::builtin_count; i++) {
|
|
||||||
if (!Builtins::IsOffHeapSafe(i)) continue;
|
|
||||||
Code* code = builtins->builtin(i);
|
|
||||||
uint32_t offset = offsets[i];
|
|
||||||
uint8_t* dst = blob + RawDataOffset() + offset;
|
|
||||||
DCHECK_LE(RawDataOffset() + offset + code->instruction_size(), blob_size);
|
|
||||||
std::memcpy(dst, code->instruction_start(), code->instruction_size());
|
|
||||||
}
|
|
||||||
|
|
||||||
return {blob, blob_size};
|
|
||||||
}
|
|
||||||
|
|
||||||
EmbeddedData EmbeddedData::FromBlob(const uint8_t* data, uint32_t size) {
|
|
||||||
return {data, size};
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t* EmbeddedData::InstructionStartOfBuiltin(int i) const {
|
|
||||||
DCHECK(Builtins::IsBuiltinId(i));
|
|
||||||
|
|
||||||
const uint32_t* offsets = Offsets();
|
|
||||||
const uint8_t* result = RawData() + offsets[i];
|
|
||||||
DCHECK_LT(result, data_ + size_);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const {
|
|
||||||
DCHECK(Builtins::IsBuiltinId(i));
|
|
||||||
const uint32_t* lengths = Lengths();
|
|
||||||
return lengths[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
EmbeddedData Snapshot::CreateEmbeddedBlob(Isolate* isolate) {
|
|
||||||
DisallowHeapAllocation no_gc;
|
|
||||||
return EmbeddedData::FromIsolate(isolate);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t Snapshot::ExtractNumContexts(const v8::StartupData* data) {
|
uint32_t Snapshot::ExtractNumContexts(const v8::StartupData* data) {
|
||||||
CHECK_LT(kNumberOfContextsOffset, data->raw_size);
|
CHECK_LT(kNumberOfContextsOffset, data->raw_size);
|
||||||
uint32_t num_contexts = GetHeaderValue(data, kNumberOfContextsOffset);
|
uint32_t num_contexts = GetHeaderValue(data, kNumberOfContextsOffset);
|
||||||
|
@ -79,60 +79,6 @@ class BuiltinSnapshotData final : public SnapshotData {
|
|||||||
// ... list of builtins offsets
|
// ... list of builtins offsets
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
class EmbeddedData final {
|
|
||||||
public:
|
|
||||||
static EmbeddedData FromIsolate(Isolate* isolate);
|
|
||||||
static EmbeddedData FromBlob(const uint8_t* data, uint32_t size);
|
|
||||||
|
|
||||||
const uint8_t* data() const { return data_; }
|
|
||||||
uint32_t size() const { return size_; }
|
|
||||||
|
|
||||||
const uint8_t* InstructionStartOfBuiltin(int i) const;
|
|
||||||
uint32_t InstructionSizeOfBuiltin(int i) const;
|
|
||||||
|
|
||||||
bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; }
|
|
||||||
|
|
||||||
// Padded with kCodeAlignment.
|
|
||||||
uint32_t PaddedInstructionSizeOfBuiltin(int i) const {
|
|
||||||
return RoundUp<kCodeAlignment>(InstructionSizeOfBuiltin(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The layout of the blob is as follows:
|
|
||||||
//
|
|
||||||
// [0] offset of instruction stream 0
|
|
||||||
// ... offsets
|
|
||||||
// [N] length of instruction stream 0
|
|
||||||
// ... lengths
|
|
||||||
// ... instruction streams
|
|
||||||
|
|
||||||
static constexpr uint32_t kTableSize = Builtins::builtin_count;
|
|
||||||
static constexpr uint32_t OffsetsOffset() { return 0; }
|
|
||||||
static constexpr uint32_t OffsetsSize() { return kUInt32Size * kTableSize; }
|
|
||||||
static constexpr uint32_t LengthsOffset() {
|
|
||||||
return OffsetsOffset() + OffsetsSize();
|
|
||||||
}
|
|
||||||
static constexpr uint32_t LengthsSize() { return kUInt32Size * kTableSize; }
|
|
||||||
static constexpr uint32_t RawDataOffset() {
|
|
||||||
return RoundUp<kCodeAlignment>(LengthsOffset() + LengthsSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
EmbeddedData(const uint8_t* data, uint32_t size) : data_(data), size_(size) {}
|
|
||||||
|
|
||||||
const uint32_t* Offsets() const {
|
|
||||||
return reinterpret_cast<const uint32_t*>(data_ + OffsetsOffset());
|
|
||||||
}
|
|
||||||
const uint32_t* Lengths() const {
|
|
||||||
return reinterpret_cast<const uint32_t*>(data_ + LengthsOffset());
|
|
||||||
}
|
|
||||||
const uint8_t* RawData() const { return data_ + RawDataOffset(); }
|
|
||||||
|
|
||||||
const uint8_t* data_;
|
|
||||||
uint32_t size_;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Snapshot : public AllStatic {
|
class Snapshot : public AllStatic {
|
||||||
public:
|
public:
|
||||||
// ---------------- Deserialization ----------------
|
// ---------------- Deserialization ----------------
|
||||||
@ -175,10 +121,6 @@ class Snapshot : public AllStatic {
|
|||||||
const std::vector<SnapshotData*>& context_snapshots,
|
const std::vector<SnapshotData*>& context_snapshots,
|
||||||
bool can_be_rehashed);
|
bool can_be_rehashed);
|
||||||
|
|
||||||
#ifdef V8_EMBEDDED_BUILTINS
|
|
||||||
static EmbeddedData CreateEmbeddedBlob(Isolate* isolate);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static bool SnapshotIsValid(const v8::StartupData* snapshot_blob);
|
static bool SnapshotIsValid(const v8::StartupData* snapshot_blob);
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "src/isolate.h"
|
#include "src/isolate.h"
|
||||||
#include "src/macro-assembler-inl.h"
|
#include "src/macro-assembler-inl.h"
|
||||||
#include "src/simulator.h"
|
#include "src/simulator.h"
|
||||||
#include "src/snapshot/macros.h"
|
|
||||||
#include "src/snapshot/snapshot.h"
|
#include "src/snapshot/snapshot.h"
|
||||||
|
|
||||||
// To generate the binary files for the test function, enable this section and
|
// To generate the binary files for the test function, enable this section and
|
||||||
@ -109,6 +108,87 @@ UNINITIALIZED_TEST(VerifyBuiltinsIsolateIndependence) {
|
|||||||
|
|
||||||
v8_isolate->Dispose();
|
v8_isolate->Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNINITIALIZED_TEST(VerifyBuiltinsOffHeapSafety) {
|
||||||
|
FLAG_stress_off_heap_code = false; // Disable off-heap trampolines.
|
||||||
|
|
||||||
|
v8::Isolate::CreateParams create_params;
|
||||||
|
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||||
|
v8::Isolate* v8_isolate = v8::Isolate::New(create_params);
|
||||||
|
|
||||||
|
{
|
||||||
|
v8::Isolate::Scope isolate_scope(v8_isolate);
|
||||||
|
v8::internal::Isolate* isolate =
|
||||||
|
reinterpret_cast<v8::internal::Isolate*>(v8_isolate);
|
||||||
|
HandleScope handle_scope(isolate);
|
||||||
|
|
||||||
|
Snapshot::EnsureAllBuiltinsAreDeserialized(isolate);
|
||||||
|
|
||||||
|
constexpr int all_real_modes_mask =
|
||||||
|
(1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - 1;
|
||||||
|
constexpr int mode_mask =
|
||||||
|
all_real_modes_mask & ~RelocInfo::ModeMask(RelocInfo::COMMENT) &
|
||||||
|
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) &
|
||||||
|
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) &
|
||||||
|
~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
|
||||||
|
~RelocInfo::ModeMask(RelocInfo::VENEER_POOL) &
|
||||||
|
~RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
|
||||||
|
STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);
|
||||||
|
STATIC_ASSERT(RelocInfo::ModeMask(RelocInfo::COMMENT) ==
|
||||||
|
(1 << RelocInfo::COMMENT));
|
||||||
|
STATIC_ASSERT(
|
||||||
|
mode_mask ==
|
||||||
|
(RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
|
||||||
|
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
||||||
|
RelocInfo::ModeMask(RelocInfo::WASM_CONTEXT_REFERENCE) |
|
||||||
|
RelocInfo::ModeMask(RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE) |
|
||||||
|
RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_HANDLE) |
|
||||||
|
RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
|
||||||
|
RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL) |
|
||||||
|
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY)));
|
||||||
|
|
||||||
|
constexpr bool kVerbose = false;
|
||||||
|
bool found_mismatch = false;
|
||||||
|
for (int i = 0; i < Builtins::builtin_count; i++) {
|
||||||
|
Code* code = isolate->builtins()->builtin(i);
|
||||||
|
|
||||||
|
if (kVerbose) {
|
||||||
|
printf("%s %s\n", Builtins::KindNameOf(i),
|
||||||
|
isolate->builtins()->name(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_off_heap_safe = true;
|
||||||
|
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
|
||||||
|
is_off_heap_safe = false;
|
||||||
|
#ifdef ENABLE_DISASSEMBLER
|
||||||
|
if (kVerbose) {
|
||||||
|
RelocInfo::Mode mode = it.rinfo()->rmode();
|
||||||
|
printf(" %s\n", RelocInfo::RelocModeName(mode));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jgruber): Remove once we properly set up the on-heap code
|
||||||
|
// trampoline.
|
||||||
|
if (Builtins::IsTooShortForOffHeapTrampoline(i)) is_off_heap_safe = false;
|
||||||
|
|
||||||
|
// Relaxed condition only checks whether the off-heap-safe list is
|
||||||
|
// valid, not whether it is complete. This is to avoid constant work
|
||||||
|
// updating the list.
|
||||||
|
bool should_be_off_heap_safe = Builtins::IsOffHeapSafe(i);
|
||||||
|
if (should_be_off_heap_safe && !is_off_heap_safe) {
|
||||||
|
found_mismatch = true;
|
||||||
|
printf("%s %s expected: %d, is: %d\n", Builtins::KindNameOf(i),
|
||||||
|
isolate->builtins()->name(i), should_be_off_heap_safe,
|
||||||
|
is_off_heap_safe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(!found_mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
v8_isolate->Dispose();
|
||||||
|
}
|
||||||
#endif // V8_EMBEDDED_BUILTINS
|
#endif // V8_EMBEDDED_BUILTINS
|
||||||
|
|
||||||
// V8_CC_MSVC is true for both MSVC and clang on windows. clang can handle
|
// V8_CC_MSVC is true for both MSVC and clang on windows. clang can handle
|
||||||
@ -221,7 +301,6 @@ TEST(GenerateTestFunctionData) {
|
|||||||
std::ofstream of(TEST_FUNCTION_FILE, std::ios::out | std::ios::binary);
|
std::ofstream of(TEST_FUNCTION_FILE, std::ios::out | std::ios::binary);
|
||||||
of.write(reinterpret_cast<char*>(desc.buffer), desc.instr_size);
|
of.write(reinterpret_cast<char*>(desc.buffer), desc.instr_size);
|
||||||
}
|
}
|
||||||
#undef __
|
|
||||||
#endif // GENERATE_TEST_FUNCTION_DATA
|
#endif // GENERATE_TEST_FUNCTION_DATA
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_IA32
|
||||||
@ -252,12 +331,48 @@ TEST(GenerateTestFunctionData) {
|
|||||||
#error "Unknown architecture."
|
#error "Unknown architecture."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
V8_EMBEDDED_RODATA_HEADER(test_string0_bytes)
|
// .byte macros to handle small differences across operating systems.
|
||||||
|
|
||||||
|
#if defined(V8_OS_MACOSX)
|
||||||
|
#define ASM_RODATA_SECTION ".const_data\n"
|
||||||
|
#define ASM_TEXT_SECTION ".text\n"
|
||||||
|
#define ASM_MANGLE_LABEL "_"
|
||||||
|
#define ASM_GLOBAL(NAME) ".globl " ASM_MANGLE_LABEL NAME "\n"
|
||||||
|
#elif defined(V8_OS_WIN)
|
||||||
|
#define ASM_RODATA_SECTION ".section .rodata\n"
|
||||||
|
#define ASM_TEXT_SECTION ".section .text\n"
|
||||||
|
#if defined(V8_TARGET_ARCH_X64)
|
||||||
|
#define ASM_MANGLE_LABEL ""
|
||||||
|
#else
|
||||||
|
#define ASM_MANGLE_LABEL "_"
|
||||||
|
#endif
|
||||||
|
#define ASM_GLOBAL(NAME) ".global " ASM_MANGLE_LABEL NAME "\n"
|
||||||
|
#else
|
||||||
|
#define ASM_RODATA_SECTION ".section .rodata\n"
|
||||||
|
#define ASM_TEXT_SECTION ".section .text\n"
|
||||||
|
#define ASM_MANGLE_LABEL ""
|
||||||
|
#define ASM_GLOBAL(NAME) ".global " ASM_MANGLE_LABEL NAME "\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#define EMBED_IN_RODATA_HEADER(LABEL) \
|
||||||
|
__asm__(ASM_RODATA_SECTION \
|
||||||
|
ASM_GLOBAL(#LABEL) \
|
||||||
|
".balign 16\n" \
|
||||||
|
ASM_MANGLE_LABEL #LABEL ":\n");
|
||||||
|
|
||||||
|
#define EMBED_IN_TEXT_HEADER(LABEL) \
|
||||||
|
__asm__(ASM_TEXT_SECTION \
|
||||||
|
ASM_GLOBAL(#LABEL) \
|
||||||
|
".balign 16\n" \
|
||||||
|
ASM_MANGLE_LABEL #LABEL ":\n");
|
||||||
|
|
||||||
|
EMBED_IN_RODATA_HEADER(test_string0_bytes)
|
||||||
__asm__(".byte 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37\n"
|
__asm__(".byte 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37\n"
|
||||||
".byte 0x38, 0x39, 0x0a, 0x00\n");
|
".byte 0x38, 0x39, 0x0a, 0x00\n");
|
||||||
extern "C" V8_ALIGNED(16) const char test_string0_bytes[];
|
extern "C" V8_ALIGNED(16) const char test_string0_bytes[];
|
||||||
|
|
||||||
V8_EMBEDDED_TEXT_HEADER(test_function0_bytes)
|
EMBED_IN_TEXT_HEADER(test_function0_bytes)
|
||||||
__asm__(FUNCTION_BYTES);
|
__asm__(FUNCTION_BYTES);
|
||||||
extern "C" V8_ALIGNED(16) const char test_function0_bytes[];
|
extern "C" V8_ALIGNED(16) const char test_function0_bytes[];
|
||||||
// clang-format on
|
// clang-format on
|
||||||
@ -281,6 +396,13 @@ TEST(ByteInText) {
|
|||||||
#endif // #ifndef V8_COMPILER_IS_MSVC
|
#endif // #ifndef V8_COMPILER_IS_MSVC
|
||||||
#undef V8_COMPILER_IS_MSVC
|
#undef V8_COMPILER_IS_MSVC
|
||||||
|
|
||||||
|
#undef __
|
||||||
|
#undef ASM_GLOBAL
|
||||||
|
#undef ASM_MANGLE_LABEL
|
||||||
|
#undef ASM_RODATA_SECTION
|
||||||
|
#undef ASM_TEXT_SECTION
|
||||||
|
#undef EMBED_IN_RODATA_HEADER
|
||||||
|
#undef EMBED_IN_TEXT_HEADER
|
||||||
#undef FUNCTION_BYTES
|
#undef FUNCTION_BYTES
|
||||||
#undef GENERATE_TEST_FUNCTION_DATA
|
#undef GENERATE_TEST_FUNCTION_DATA
|
||||||
#undef TEST_FUNCTION_FILE
|
#undef TEST_FUNCTION_FILE
|
||||||
|
Loading…
Reference in New Issue
Block a user