Commit 6b2a49ff authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

* Modify simulator and ARM code generator to avoid swi

instructions.  The intention is that the snapshots generated
by the simulator should be usable on the hardware.  Instead of
swi instructions we generate a branch to a swi instruction that
is not part of the snapshot.  The call/jump is patched up in
the same way as other external references when the snapshot
is deserialized.  This only works for EABI targets: on old ABI
targets we still emit some instructions not supported by the
simulator (fp coprocessor instructions).
Review URL: http://codereview.chromium.org/119036

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2127 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4a96feee
......@@ -4384,7 +4384,6 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
Label* not_smi,
const Builtins::JavaScript& builtin,
Token::Value operation,
int swi_number,
OverwriteMode mode) {
Label slow;
__ bind(&slow);
......@@ -4432,23 +4431,17 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
__ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
// Call C routine that may not cause GC or other trouble.
__ mov(r5, Operand(ExternalReference::double_fp_operation(operation)));
#if !defined(__arm__)
// Notify the simulator that we are calling an add routine in C.
__ swi(swi_number);
#else
// Actually call the add routine written in C.
__ Call(r5);
#endif
// Store answer in the overwritable heap number.
__ pop(r4);
#if !defined(__ARM_EABI__) && defined(__arm__)
#if !defined(USE_ARM_EABI)
// Double returned in fp coprocessor register 0 and 1, encoded as register
// cr8. Offsets must be divisible by 4 for coprocessor so we need to
// substract the tag from r4.
__ sub(r5, r4, Operand(kHeapObjectTag));
__ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset));
#else
// Double returned in fp coprocessor register 0 and 1.
// Double returned in registers 0 and 1.
__ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset));
__ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + kPointerSize));
#endif
......@@ -4483,7 +4476,6 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
&not_smi,
Builtins::ADD,
Token::ADD,
assembler::arm::simulator_fp_add,
mode_);
break;
}
......@@ -4503,7 +4495,6 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
&not_smi,
Builtins::SUB,
Token::SUB,
assembler::arm::simulator_fp_sub,
mode_);
break;
}
......@@ -4532,7 +4523,6 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
&not_smi,
Builtins::MUL,
Token::MUL,
assembler::arm::simulator_fp_mul,
mode_);
break;
}
......@@ -4793,7 +4783,8 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
if (do_gc) {
// Passing r0.
__ Call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY);
ExternalReference gc_reference = ExternalReference::perform_gc_function();
__ Call(gc_reference.address(), RelocInfo::RUNTIME_ENTRY);
}
ExternalReference scope_depth =
......@@ -4819,12 +4810,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
// sequence that it is not moving ever.
__ add(lr, pc, Operand(4)); // compute return address: (pc + 8) + 4
__ push(lr);
#if !defined(__arm__)
// Notify the simulator of the transition to C code.
__ swi(assembler::arm::call_rt_r5);
#else /* !defined(__arm__) */
__ Jump(r5);
#endif /* !defined(__arm__) */
if (always_allocate) {
// It's okay to clobber r2 and r3 here. Don't mess with r0 and r1
......
// Copyright 2008 the V8 project authors. All rights reserved.
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -28,6 +28,14 @@
#ifndef V8_ARM_CONSTANTS_ARM_H_
#define V8_ARM_CONSTANTS_ARM_H_
// The simulator emulates the EABI so we define the USE_ARM_EABI macro if we
// are not running on real ARM hardware. One reason for this is that the
// old ABI uses fp registers in the calling convention and the simulator does
// not simulate fp registers or coroutine instructions.
#if defined(__ARM_EABI__) || !defined(__arm__)
# define USE_ARM_EABI 1
#endif
namespace assembler {
namespace arm {
......@@ -104,15 +112,9 @@ enum Shift {
// simulator.
enum SoftwareInterruptCodes {
// transition to C code
call_rt_r5 = 0x10,
call_rt_r2 = 0x11,
call_rt_redirected = 0x10,
// break point
break_point = 0x20,
// FP operations. These simulate calling into C for a moment to do fp ops.
// They should trash all caller-save registers.
simulator_fp_add = 0x21,
simulator_fp_sub = 0x22,
simulator_fp_mul = 0x23
break_point = 0x20
};
......
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -46,6 +46,8 @@ void CPU::FlushICache(void* start, size_t size) {
#if !defined (__arm__)
// Not generating ARM instructions for C-code. This means that we are
// building an ARM emulator based target. No I$ flushes are necessary.
// None of this code ends up in the snapshot so there are no issues
// around whether or not to generate the code when building snapshots.
#else
// Ideally, we would call
// syscall(__ARM_NR_cacheflush, start,
......
// Copyright 2007-2008 the V8 project authors. All rights reserved.
// Copyright 2007-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -253,24 +253,12 @@ void Decoder::PrintPU(Instr* instr) {
// the FormatOption method.
void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
switch (swi) {
case call_rt_r5:
Print("call_rt_r5");
return;
case call_rt_r2:
Print("call_rt_r2");
case call_rt_redirected:
Print("call_rt_redirected");
return;
case break_point:
Print("break_point");
return;
case simulator_fp_add:
Print("simulator_fp_add");
return;
case simulator_fp_mul:
Print("simulator_fp_mul");
return;
case simulator_fp_sub:
Print("simulator_fp_sub");
return;
default:
out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"%d",
......
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -128,26 +128,10 @@ void MacroAssembler::Call(Register target, Condition cond) {
void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
Condition cond) {
#if !defined(__arm__)
if (rmode == RelocInfo::RUNTIME_ENTRY) {
mov(r2, Operand(target, rmode), LeaveCC, cond);
// Set lr for return at current pc + 8.
mov(lr, Operand(pc), LeaveCC, cond);
// Emit a ldr<cond> pc, [pc + offset of target in constant pool].
// Notify the simulator of the transition to C code.
swi(assembler::arm::call_rt_r2);
} else {
// set lr for return at current pc + 8
mov(lr, Operand(pc), LeaveCC, cond);
// emit a ldr<cond> pc, [pc + offset of target in constant pool]
mov(pc, Operand(target, rmode), LeaveCC, cond);
}
#else
// Set lr for return at current pc + 8.
mov(lr, Operand(pc), LeaveCC, cond);
// Emit a ldr<cond> pc, [pc + offset of target in constant pool].
mov(pc, Operand(target, rmode), LeaveCC, cond);
#endif // !defined(__arm__)
// If USE_BLX is defined, we could emit a 'mov ip, target', followed by a
// 'blx ip'; however, the code would not be shorter than the above sequence
// and the target address of the call would be referenced by the first
......
// Copyright 2008 the V8 project authors. All rights reserved.
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -30,6 +30,7 @@
#include "v8.h"
#include "disasm.h"
#include "assembler.h"
#include "arm/constants-arm.h"
#include "arm/simulator-arm.h"
......@@ -380,7 +381,23 @@ void Debugger::Debug() {
}
// Create one simulator per thread and keep it in thread local storage.
static v8::internal::Thread::LocalStorageKey simulator_key;
bool Simulator::initialized_ = false;
void Simulator::Initialize() {
if (initialized_) return;
simulator_key = v8::internal::Thread::CreateThreadLocalKey();
initialized_ = true;
::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
}
Simulator::Simulator() {
ASSERT(initialized_);
// Setup simulator support first. Some of this information is needed to
// setup the architecture state.
size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
......@@ -412,9 +429,63 @@ Simulator::Simulator() {
}
// Create one simulator per thread and keep it in thread local storage.
static v8::internal::Thread::LocalStorageKey simulator_key =
v8::internal::Thread::CreateThreadLocalKey();
// When the generated code calls an external reference we need to catch that in
// the simulator. The external reference will be a function compiled for the
// host architecture. We need to call that function instead of trying to
// execute it with the simulator. We do that by redirecting the external
// reference to a swi (software-interrupt) instruction that is handled by
// the simulator. We write the original destination of the jump just at a known
// offset from the swi instruction so the simulator knows what to call.
class Redirection {
public:
Redirection(void* external_function, bool fp_return)
: external_function_(external_function),
swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected),
fp_return_(fp_return),
next_(list_) {
list_ = this;
}
void* address_of_swi_instruction() {
return reinterpret_cast<void*>(&swi_instruction_);
}
void* external_function() { return external_function_; }
bool fp_return() { return fp_return_; }
static Redirection* Get(void* external_function, bool fp_return) {
Redirection* current;
for (current = list_; current != NULL; current = current->next_) {
if (current->external_function_ == external_function) return current;
}
return new Redirection(external_function, fp_return);
}
static Redirection* FromSwiInstruction(Instr* swi_instruction) {
char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
char* addr_of_redirection =
addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
return reinterpret_cast<Redirection*>(addr_of_redirection);
}
private:
void* external_function_;
uint32_t swi_instruction_;
bool fp_return_;
Redirection* next_;
static Redirection* list_;
};
Redirection* Redirection::list_ = NULL;
void* Simulator::RedirectExternalReference(void* external_function,
bool fp_return) {
Redirection* redirection = Redirection::Get(external_function, fp_return);
return redirection->address_of_swi_instruction();
}
// Get the active Simulator for the current thread.
Simulator* Simulator::current() {
......@@ -921,7 +992,14 @@ void Simulator::HandleRList(Instr* instr, bool load) {
// 64-bit value. With the code below we assume that all runtime calls return
// 64 bits of result. If they don't, the r1 result register contains a bogus
// value, which is fine because it is caller-saved.
typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1);
typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
int32_t arg1,
int32_t arg2,
int32_t arg3);
typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
int32_t arg1,
int32_t arg2,
int32_t arg3);
// Software interrupt instructions are used by the simulator to call into the
......@@ -929,30 +1007,51 @@ typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1);
void Simulator::SoftwareInterrupt(Instr* instr) {
int swi = instr->SwiField();
switch (swi) {
case call_rt_r5: {
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(get_register(r5));
intptr_t arg0 = get_register(r0);
intptr_t arg1 = get_register(r1);
int64_t result = target(arg0, arg1);
int32_t lo_res = static_cast<int32_t>(result);
int32_t hi_res = static_cast<int32_t>(result >> 32);
set_register(r0, lo_res);
set_register(r1, hi_res);
set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
break;
}
case call_rt_r2: {
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(get_register(r2));
intptr_t arg0 = get_register(r0);
intptr_t arg1 = get_register(r1);
int64_t result = target(arg0, arg1);
int32_t lo_res = static_cast<int32_t>(result);
int32_t hi_res = static_cast<int32_t>(result >> 32);
set_register(r0, lo_res);
set_register(r1, hi_res);
set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
case call_rt_redirected: {
Redirection* redirection = Redirection::FromSwiInstruction(instr);
int32_t arg0 = get_register(r0);
int32_t arg1 = get_register(r1);
int32_t arg2 = get_register(r2);
int32_t arg3 = get_register(r3);
// This is dodgy but it works because the C entry stubs are never moved.
// See comment in codegen-arm.cc and bug 1242173.
int32_t saved_lr = get_register(lr);
if (redirection->fp_return()) {
intptr_t external =
reinterpret_cast<intptr_t>(redirection->external_function());
SimulatorRuntimeFPCall target =
reinterpret_cast<SimulatorRuntimeFPCall>(external);
if (::v8::internal::FLAG_trace_sim) {
double x, y;
GetFpArgs(&x, &y);
PrintF("Call to host function at %p with args %f, %f\n",
FUNCTION_ADDR(target), x, y);
}
double result = target(arg0, arg1, arg2, arg3);
SetFpResult(result);
} else {
intptr_t external =
reinterpret_cast<int32_t>(redirection->external_function());
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
if (::v8::internal::FLAG_trace_sim) {
PrintF(
"Call to host function at %p with args %08x, %08x, %08x, %08x\n",
FUNCTION_ADDR(target),
arg0,
arg1,
arg2,
arg3);
}
int64_t result = target(arg0, arg1, arg2, arg3);
int32_t lo_res = static_cast<int32_t>(result);
int32_t hi_res = static_cast<int32_t>(result >> 32);
set_register(r0, lo_res);
set_register(r1, hi_res);
set_register(r0, result);
}
set_register(lr, saved_lr);
set_pc(get_register(lr));
break;
}
case break_point: {
......@@ -960,30 +1059,6 @@ void Simulator::SoftwareInterrupt(Instr* instr) {
dbg.Debug();
break;
}
{
double x, y, z;
case simulator_fp_add:
GetFpArgs(&x, &y);
z = x + y;
SetFpResult(z);
TrashCallerSaveRegisters();
set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
break;
case simulator_fp_sub:
GetFpArgs(&x, &y);
z = x - y;
SetFpResult(z);
TrashCallerSaveRegisters();
set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
break;
case simulator_fp_mul:
GetFpArgs(&x, &y);
z = x * y;
SetFpResult(z);
TrashCallerSaveRegisters();
set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
break;
}
default: {
UNREACHABLE();
break;
......
// Copyright 2008 the V8 project authors. All rights reserved.
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -106,6 +106,9 @@ class Simulator {
// Executes ARM instructions until the PC reaches end_sim_pc.
void Execute();
// Call on program start.
static void Initialize();
// V8 generally calls into generated code with 5 parameters. This is a
// convenience function, which sets up the simulator state and grabs the
// result on return.
......@@ -175,6 +178,10 @@ class Simulator {
// Executes one instruction.
void InstructionDecode(Instr* instr);
// Runtime call support.
static void* RedirectExternalReference(void* external_function,
bool fp_return);
// For use in calls that take two double values, constructed from r0, r1, r2
// and r3.
void GetFpArgs(double* x, double* y);
......@@ -192,6 +199,7 @@ class Simulator {
char* stack_;
bool pc_modified_;
int icount_;
static bool initialized_;
// registered breakpoints
Instr* break_pc_;
......
......@@ -30,7 +30,7 @@
// The original source code covered by the above license above has been
// modified significantly by Google Inc.
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-2009 the V8 project authors. All rights reserved.
#include "v8.h"
......@@ -508,7 +508,7 @@ void RelocInfo::Verify() {
// Implementation of ExternalReference
ExternalReference::ExternalReference(Builtins::CFunctionId id)
: address_(Builtins::c_function_address(id)) {}
: address_(Redirect(Builtins::c_function_address(id))) {}
ExternalReference::ExternalReference(Builtins::Name name)
......@@ -516,15 +516,15 @@ ExternalReference::ExternalReference(Builtins::Name name)
ExternalReference::ExternalReference(Runtime::FunctionId id)
: address_(Runtime::FunctionForId(id)->entry) {}
: address_(Redirect(Runtime::FunctionForId(id)->entry)) {}
ExternalReference::ExternalReference(Runtime::Function* f)
: address_(f->entry) {}
: address_(Redirect(f->entry)) {}
ExternalReference::ExternalReference(const IC_Utility& ic_utility)
: address_(ic_utility.address()) {}
: address_(Redirect(ic_utility.address())) {}
#ifdef ENABLE_DEBUGGER_SUPPORT
ExternalReference::ExternalReference(const Debug_Address& debug_address)
......@@ -543,10 +543,16 @@ ExternalReference::ExternalReference(const SCTableReference& table_ref)
: address_(table_ref.address()) {}
ExternalReference ExternalReference::perform_gc_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(Runtime::PerformGC)));
}
ExternalReference ExternalReference::builtin_passed_function() {
return ExternalReference(&Builtins::builtin_passed_function);
}
ExternalReference ExternalReference::the_hole_value_location() {
return ExternalReference(Factory::the_hole_value().location());
}
......@@ -614,13 +620,17 @@ ExternalReference ExternalReference::double_fp_operation(
default:
UNREACHABLE();
}
return ExternalReference(FUNCTION_ADDR(function));
// Passing true as 2nd parameter indicates that they return an fp value.
return ExternalReference(Redirect(FUNCTION_ADDR(function), true));
}
ExternalReferenceRedirector* ExternalReference::redirector_ = NULL;
#ifdef ENABLE_DEBUGGER_SUPPORT
ExternalReference ExternalReference::debug_break() {
return ExternalReference(FUNCTION_ADDR(Debug::Break));
return ExternalReference(Redirect(FUNCTION_ADDR(Debug::Break)));
}
......
......@@ -30,7 +30,7 @@
// The original source code covered by the above license above has been
// modified significantly by Google Inc.
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-2009 the V8 project authors. All rights reserved.
#ifndef V8_ASSEMBLER_H_
#define V8_ASSEMBLER_H_
......@@ -352,10 +352,15 @@ class SCTableReference;
class Debug_Address;
#endif
// An ExternalReference represents a C++ address called from the generated
// code. All references to C++ functions and must be encapsulated in an
// ExternalReference instance. This is done in order to track the origin of
// all external references in the code.
typedef void* ExternalReferenceRedirector(void* original, bool fp_return);
// An ExternalReference represents a C++ address used in the generated
// code. All references to C++ functions and variables must be encapsulated in
// an ExternalReference instance. This is done in order to track the origin of
// all external references in the code so that they can be bound to the correct
// addresses when deserializing a heap.
class ExternalReference BASE_EMBEDDED {
public:
explicit ExternalReference(Builtins::CFunctionId id);
......@@ -382,6 +387,8 @@ class ExternalReference BASE_EMBEDDED {
// pattern. This means that they have to be added to the
// ExternalReferenceTable in serialize.cc manually.
static ExternalReference perform_gc_function();
static ExternalReference builtin_passed_function();
// Static variable Factory::the_hole_value.location()
......@@ -403,7 +410,7 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference double_fp_operation(Token::Value operation);
Address address() const {return address_;}
Address address() const {return reinterpret_cast<Address>(address_);}
#ifdef ENABLE_DEBUGGER_SUPPORT
// Function Debug::Break()
......@@ -413,11 +420,30 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference debug_step_in_fp_address();
#endif
// This lets you register a function that rewrites all external references.
// Used by the ARM simulator to catch calls to external references.
static void set_redirector(ExternalReferenceRedirector* redirector) {
ASSERT(redirector_ == NULL); // We can't stack them.
redirector_ = redirector;
}
private:
explicit ExternalReference(void* address)
: address_(reinterpret_cast<Address>(address)) {}
: address_(address) {}
static ExternalReferenceRedirector* redirector_;
static void* Redirect(void* address, bool fp_return = false) {
if (redirector_ == NULL) return address;
return (*redirector_)(address, fp_return);
}
static void* Redirect(Address address_arg, bool fp_return = false) {
void* address = reinterpret_cast<void*>(address_arg);
return redirector_ == NULL ? address : (*redirector_)(address, fp_return);
}
Address address_;
void* address_;
};
......
......@@ -450,20 +450,26 @@ void ExternalReferenceTable::AddFromId(TypeCode type,
const char* name) {
Address address;
switch (type) {
case C_BUILTIN:
address = Builtins::c_function_address(
static_cast<Builtins::CFunctionId>(id));
case C_BUILTIN: {
ExternalReference ref(static_cast<Builtins::CFunctionId>(id));
address = ref.address();
break;
case BUILTIN:
address = Builtins::builtin_address(static_cast<Builtins::Name>(id));
}
case BUILTIN: {
ExternalReference ref(static_cast<Builtins::Name>(id));
address = ref.address();
break;
case RUNTIME_FUNCTION:
address = Runtime::FunctionForId(
static_cast<Runtime::FunctionId>(id))->entry;
}
case RUNTIME_FUNCTION: {
ExternalReference ref(static_cast<Runtime::FunctionId>(id));
address = ref.address();
break;
case IC_UTILITY:
address = IC::AddressFromUtilityId(static_cast<IC::UtilityId>(id));
}
case IC_UTILITY: {
ExternalReference ref(IC_Utility(static_cast<IC::UtilityId>(id)));
address = ref.address();
break;
}
default:
UNREACHABLE();
return;
......@@ -642,7 +648,7 @@ void ExternalReferenceTable::PopulateTable() {
"StubCache::secondary_->value");
// Runtime entries
Add(FUNCTION_ADDR(Runtime::PerformGC),
Add(ExternalReference::perform_gc_function().address(),
RUNTIME_ENTRY,
1,
"Runtime::PerformGC");
......
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -33,6 +33,10 @@
#include "stub-cache.h"
#include "oprofile-agent.h"
#if V8_TARGET_ARCH_ARM
#include "arm/simulator-arm.h"
#endif
namespace v8 {
namespace internal {
......@@ -62,6 +66,11 @@ bool V8::Initialize(Deserializer *des) {
// Setup the platform OS support.
OS::Setup();
// Initialize other runtime facilities
#if !V8_HOST_ARCH_ARM && V8_TARGET_ARCH_ARM
::assembler::arm::Simulator::Initialize();
#endif
// Setup the object heap
ASSERT(!Heap::HasBeenSetup());
if (!Heap::Setup(create_heap_objects)) {
......@@ -69,7 +78,6 @@ bool V8::Initialize(Deserializer *des) {
return false;
}
// Initialize other runtime facilities
Bootstrapper::Initialize(create_heap_objects);
Builtins::Setup(create_heap_objects);
Top::Initialize();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment