| Index: src/arm/simulator-arm.cc
|
| ===================================================================
|
| --- src/arm/simulator-arm.cc (revision 7267)
|
| +++ src/arm/simulator-arm.cc (working copy)
|
| @@ -49,12 +49,12 @@
|
| // Windows C Run-Time Library does not provide vsscanf.
|
| #define SScanF sscanf // NOLINT
|
|
|
| -// The Debugger class is used by the simulator while debugging simulated ARM
|
| +// The ArmDebugger class is used by the simulator while debugging simulated ARM
|
| // code.
|
| -class Debugger {
|
| +class ArmDebugger {
|
| public:
|
| - explicit Debugger(Simulator* sim);
|
| - ~Debugger();
|
| + explicit ArmDebugger(Simulator* sim);
|
| + ~ArmDebugger();
|
|
|
| void Stop(Instruction* instr);
|
| void Debug();
|
| @@ -83,12 +83,12 @@
|
| };
|
|
|
|
|
| -Debugger::Debugger(Simulator* sim) {
|
| +ArmDebugger::ArmDebugger(Simulator* sim) {
|
| sim_ = sim;
|
| }
|
|
|
|
|
| -Debugger::~Debugger() {
|
| +ArmDebugger::~ArmDebugger() {
|
| }
|
|
|
|
|
| @@ -105,7 +105,7 @@
|
| }
|
|
|
|
|
| -void Debugger::Stop(Instruction* instr) {
|
| +void ArmDebugger::Stop(Instruction* instr) {
|
| // Get the stop code.
|
| uint32_t code = instr->SvcValue() & kStopCodeMask;
|
| // Retrieve the encoded address, which comes just after this stop.
|
| @@ -137,7 +137,7 @@
|
| }
|
|
|
|
|
| -void Debugger::Stop(Instruction* instr) {
|
| +void ArmDebugger::Stop(Instruction* instr) {
|
| // Get the stop code.
|
| uint32_t code = instr->SvcValue() & kStopCodeMask;
|
| // Retrieve the encoded address, which comes just after this stop.
|
| @@ -159,7 +159,7 @@
|
| #endif
|
|
|
|
|
| -int32_t Debugger::GetRegisterValue(int regnum) {
|
| +int32_t ArmDebugger::GetRegisterValue(int regnum) {
|
| if (regnum == kPCRegister) {
|
| return sim_->get_pc();
|
| } else {
|
| @@ -168,12 +168,12 @@
|
| }
|
|
|
|
|
| -double Debugger::GetVFPDoubleRegisterValue(int regnum) {
|
| +double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
|
| return sim_->get_double_from_d_register(regnum);
|
| }
|
|
|
|
|
| -bool Debugger::GetValue(const char* desc, int32_t* value) {
|
| +bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
|
| int regnum = Registers::Number(desc);
|
| if (regnum != kNoRegister) {
|
| *value = GetRegisterValue(regnum);
|
| @@ -189,7 +189,7 @@
|
| }
|
|
|
|
|
| -bool Debugger::GetVFPSingleValue(const char* desc, float* value) {
|
| +bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
|
| bool is_double;
|
| int regnum = VFPRegisters::Number(desc, &is_double);
|
| if (regnum != kNoRegister && !is_double) {
|
| @@ -200,7 +200,7 @@
|
| }
|
|
|
|
|
| -bool Debugger::GetVFPDoubleValue(const char* desc, double* value) {
|
| +bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
|
| bool is_double;
|
| int regnum = VFPRegisters::Number(desc, &is_double);
|
| if (regnum != kNoRegister && is_double) {
|
| @@ -211,7 +211,7 @@
|
| }
|
|
|
|
|
| -bool Debugger::SetBreakpoint(Instruction* breakpc) {
|
| +bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
|
| // Check if a breakpoint can be set. If not return without any side-effects.
|
| if (sim_->break_pc_ != NULL) {
|
| return false;
|
| @@ -226,7 +226,7 @@
|
| }
|
|
|
|
|
| -bool Debugger::DeleteBreakpoint(Instruction* breakpc) {
|
| +bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
|
| if (sim_->break_pc_ != NULL) {
|
| sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
|
| }
|
| @@ -237,21 +237,21 @@
|
| }
|
|
|
|
|
| -void Debugger::UndoBreakpoints() {
|
| +void ArmDebugger::UndoBreakpoints() {
|
| if (sim_->break_pc_ != NULL) {
|
| sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
|
| }
|
| }
|
|
|
|
|
| -void Debugger::RedoBreakpoints() {
|
| +void ArmDebugger::RedoBreakpoints() {
|
| if (sim_->break_pc_ != NULL) {
|
| sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
|
| }
|
| }
|
|
|
|
|
| -void Debugger::Debug() {
|
| +void ArmDebugger::Debug() {
|
| intptr_t last_pc = -1;
|
| bool done = false;
|
|
|
| @@ -539,7 +539,7 @@
|
| PrintF(" Stops are debug instructions inserted by\n");
|
| PrintF(" the Assembler::stop() function.\n");
|
| PrintF(" When hitting a stop, the Simulator will\n");
|
| - PrintF(" stop and and give control to the Debugger.\n");
|
| + PrintF(" stop and and give control to the ArmDebugger.\n");
|
| PrintF(" The first %d stop codes are watched:\n",
|
| Simulator::kNumOfWatchedStops);
|
| PrintF(" - They can be enabled / disabled: the Simulator\n");
|
| @@ -593,7 +593,9 @@
|
| }
|
|
|
|
|
| -void Simulator::FlushICache(void* start_addr, size_t size) {
|
| +void Simulator::FlushICache(v8::internal::HashMap* i_cache,
|
| + void* start_addr,
|
| + size_t size) {
|
| intptr_t start = reinterpret_cast<intptr_t>(start_addr);
|
| int intra_line = (start & CachePage::kLineMask);
|
| start -= intra_line;
|
| @@ -602,22 +604,22 @@
|
| int offset = (start & CachePage::kPageMask);
|
| while (!AllOnOnePage(start, size - 1)) {
|
| int bytes_to_flush = CachePage::kPageSize - offset;
|
| - FlushOnePage(start, bytes_to_flush);
|
| + FlushOnePage(i_cache, start, bytes_to_flush);
|
| start += bytes_to_flush;
|
| size -= bytes_to_flush;
|
| ASSERT_EQ(0, start & CachePage::kPageMask);
|
| offset = 0;
|
| }
|
| if (size != 0) {
|
| - FlushOnePage(start, size);
|
| + FlushOnePage(i_cache, start, size);
|
| }
|
| }
|
|
|
|
|
| -CachePage* Simulator::GetCachePage(void* page) {
|
| - v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page,
|
| - ICacheHash(page),
|
| - true);
|
| +CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
|
| + v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
|
| + ICacheHash(page),
|
| + true);
|
| if (entry->value == NULL) {
|
| CachePage* new_page = new CachePage();
|
| entry->value = new_page;
|
| @@ -627,25 +629,28 @@
|
|
|
|
|
| // Flush from start up to and not including start + size.
|
| -void Simulator::FlushOnePage(intptr_t start, int size) {
|
| +void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
|
| + intptr_t start,
|
| + int size) {
|
| ASSERT(size <= CachePage::kPageSize);
|
| ASSERT(AllOnOnePage(start, size - 1));
|
| ASSERT((start & CachePage::kLineMask) == 0);
|
| ASSERT((size & CachePage::kLineMask) == 0);
|
| void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
|
| int offset = (start & CachePage::kPageMask);
|
| - CachePage* cache_page = GetCachePage(page);
|
| + CachePage* cache_page = GetCachePage(i_cache, page);
|
| char* valid_bytemap = cache_page->ValidityByte(offset);
|
| memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
|
| }
|
|
|
|
|
| -void Simulator::CheckICache(Instruction* instr) {
|
| +void Simulator::CheckICache(v8::internal::HashMap* i_cache,
|
| + Instruction* instr) {
|
| intptr_t address = reinterpret_cast<intptr_t>(instr);
|
| void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
|
| void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
|
| int offset = (address & CachePage::kPageMask);
|
| - CachePage* cache_page = GetCachePage(page);
|
| + CachePage* cache_page = GetCachePage(i_cache, page);
|
| char* cache_valid_byte = cache_page->ValidityByte(offset);
|
| bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
|
| char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
|
| @@ -662,27 +667,18 @@
|
| }
|
|
|
|
|
| -// 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;
|
| + if (Isolate::Current()->simulator_initialized()) return;
|
| + Isolate::Current()->set_simulator_initialized(true);
|
| ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
|
| }
|
|
|
|
|
| -v8::internal::HashMap* Simulator::i_cache_ = NULL;
|
| -
|
| -
|
| -Simulator::Simulator() {
|
| +Simulator::Simulator() : isolate_(Isolate::Current()) {
|
| + i_cache_ = isolate_->simulator_i_cache();
|
| if (i_cache_ == NULL) {
|
| i_cache_ = new v8::internal::HashMap(&ICacheMatch);
|
| + isolate_->set_simulator_i_cache(i_cache_);
|
| }
|
| Initialize();
|
| // Setup simulator support first. Some of this information is needed to
|
| @@ -748,11 +744,14 @@
|
| : external_function_(external_function),
|
| swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
|
| type_(type),
|
| - next_(list_) {
|
| - Simulator::current()->
|
| - FlushICache(reinterpret_cast<void*>(&swi_instruction_),
|
| - Instruction::kInstrSize);
|
| - list_ = this;
|
| + next_(NULL) {
|
| + Isolate* isolate = Isolate::Current();
|
| + next_ = isolate->simulator_redirection();
|
| + Simulator::current(isolate)->
|
| + FlushICache(isolate->simulator_i_cache(),
|
| + reinterpret_cast<void*>(&swi_instruction_),
|
| + Instruction::kInstrSize);
|
| + isolate->set_simulator_redirection(this);
|
| }
|
|
|
| void* address_of_swi_instruction() {
|
| @@ -764,8 +763,9 @@
|
|
|
| static Redirection* Get(void* external_function,
|
| ExternalReference::Type type) {
|
| - Redirection* current;
|
| - for (current = list_; current != NULL; current = current->next_) {
|
| + Isolate* isolate = Isolate::Current();
|
| + Redirection* current = isolate->simulator_redirection();
|
| + for (; current != NULL; current = current->next_) {
|
| if (current->external_function_ == external_function) return current;
|
| }
|
| return new Redirection(external_function, type);
|
| @@ -783,13 +783,9 @@
|
| uint32_t swi_instruction_;
|
| ExternalReference::Type type_;
|
| Redirection* next_;
|
| - static Redirection* list_;
|
| };
|
|
|
|
|
| -Redirection* Redirection::list_ = NULL;
|
| -
|
| -
|
| void* Simulator::RedirectExternalReference(void* external_function,
|
| ExternalReference::Type type) {
|
| Redirection* redirection = Redirection::Get(external_function, type);
|
| @@ -798,14 +794,20 @@
|
|
|
|
|
| // Get the active Simulator for the current thread.
|
| -Simulator* Simulator::current() {
|
| - Initialize();
|
| - Simulator* sim = reinterpret_cast<Simulator*>(
|
| - v8::internal::Thread::GetThreadLocal(simulator_key));
|
| +Simulator* Simulator::current(Isolate* isolate) {
|
| + v8::internal::Isolate::PerIsolateThreadData* isolate_data =
|
| + Isolate::CurrentPerIsolateThreadData();
|
| + if (isolate_data == NULL) {
|
| + Isolate::EnterDefaultIsolate();
|
| + isolate_data = Isolate::CurrentPerIsolateThreadData();
|
| + }
|
| + ASSERT(isolate_data != NULL);
|
| +
|
| + Simulator* sim = isolate_data->simulator();
|
| if (sim == NULL) {
|
| - // TODO(146): delete the simulator object when a thread goes away.
|
| + // TODO(146): delete the simulator object when a thread/isolate goes away.
|
| sim = new Simulator();
|
| - v8::internal::Thread::SetThreadLocal(simulator_key, sim);
|
| + isolate_data->set_simulator(sim);
|
| }
|
| return sim;
|
| }
|
| @@ -1533,7 +1535,8 @@
|
| int32_t arg1,
|
| int32_t arg2,
|
| int32_t arg3,
|
| - int32_t arg4);
|
| + int32_t arg4,
|
| + int32_t arg5);
|
| typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
|
| int32_t arg1,
|
| int32_t arg2,
|
| @@ -1564,7 +1567,8 @@
|
| int32_t arg2 = get_register(r2);
|
| int32_t arg3 = get_register(r3);
|
| int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
|
| - int32_t arg4 = *stack_pointer;
|
| + int32_t arg4 = stack_pointer[0];
|
| + int32_t arg5 = stack_pointer[1];
|
| // 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);
|
| @@ -1627,20 +1631,22 @@
|
| reinterpret_cast<SimulatorRuntimeCall>(external);
|
| if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
|
| PrintF(
|
| - "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc",
|
| + "Call to host function at %p"
|
| + "args %08x, %08x, %08x, %08x, %08x, %08x",
|
| FUNCTION_ADDR(target),
|
| arg0,
|
| arg1,
|
| arg2,
|
| arg3,
|
| - arg4);
|
| + arg4,
|
| + arg5);
|
| if (!stack_aligned) {
|
| PrintF(" with unaligned stack %08x\n", get_register(sp));
|
| }
|
| PrintF("\n");
|
| }
|
| CHECK(stack_aligned);
|
| - int64_t result = target(arg0, arg1, arg2, arg3, arg4);
|
| + int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
| int32_t lo_res = static_cast<int32_t>(result);
|
| int32_t hi_res = static_cast<int32_t>(result >> 32);
|
| if (::v8::internal::FLAG_trace_sim) {
|
| @@ -1654,7 +1660,7 @@
|
| break;
|
| }
|
| case kBreakpoint: {
|
| - Debugger dbg(this);
|
| + ArmDebugger dbg(this);
|
| dbg.Debug();
|
| break;
|
| }
|
| @@ -1668,7 +1674,7 @@
|
| // Stop if it is enabled, otherwise go on jumping over the stop
|
| // and the message address.
|
| if (isEnabledStop(code)) {
|
| - Debugger dbg(this);
|
| + ArmDebugger dbg(this);
|
| dbg.Stop(instr);
|
| } else {
|
| set_pc(get_pc() + 2 * Instruction::kInstrSize);
|
| @@ -1976,7 +1982,7 @@
|
| break;
|
| }
|
| case BKPT: {
|
| - Debugger dbg(this);
|
| + ArmDebugger dbg(this);
|
| PrintF("Simulator hit BKPT.\n");
|
| dbg.Debug();
|
| break;
|
| @@ -2964,7 +2970,7 @@
|
| // Executes the current instruction.
|
| void Simulator::InstructionDecode(Instruction* instr) {
|
| if (v8::internal::FLAG_check_icache) {
|
| - CheckICache(instr);
|
| + CheckICache(isolate_->simulator_i_cache(), instr);
|
| }
|
| pc_modified_ = false;
|
| if (::v8::internal::FLAG_trace_sim) {
|
| @@ -3047,7 +3053,7 @@
|
| Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
|
| icount_++;
|
| if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
|
| - Debugger dbg(this);
|
| + ArmDebugger dbg(this);
|
| dbg.Debug();
|
| } else {
|
| InstructionDecode(instr);
|
|
|