diff options
author | Ben Murdoch <benm@google.com> | 2011-12-02 17:19:32 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-12-02 17:27:49 +0000 |
commit | 3fb3ca8c7ca439d408449a395897395c0faae8d1 (patch) | |
tree | 5cb33db083ae7ebe431e2a460fb3806c54531f9c /src/deoptimizer.cc | |
parent | 257744e915dfc84d6d07a6b2accf8402d9ffc708 (diff) | |
download | android_external_v8-3fb3ca8c7ca439d408449a395897395c0faae8d1.tar.gz android_external_v8-3fb3ca8c7ca439d408449a395897395c0faae8d1.tar.bz2 android_external_v8-3fb3ca8c7ca439d408449a395897395c0faae8d1.zip |
Upgrade to V8 3.4
Merge 3.4.14.35
Simple merge required updates to makefiles only.
Bug: 568872
Change-Id: I403a38452c547e06fcfa951c12eca12a1bc40978
Diffstat (limited to 'src/deoptimizer.cc')
-rw-r--r-- | src/deoptimizer.cc | 241 |
1 files changed, 230 insertions, 11 deletions
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index 2fc0e47b..c90df459 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -44,6 +44,9 @@ DeoptimizerData::DeoptimizerData() { lazy_deoptimization_entry_code_ = NULL; current_ = NULL; deoptimizing_code_list_ = NULL; +#ifdef ENABLE_DEBUGGER_SUPPORT + deoptimized_frame_info_ = NULL; +#endif } @@ -58,6 +61,16 @@ DeoptimizerData::~DeoptimizerData() { } } + +#ifdef ENABLE_DEBUGGER_SUPPORT +void DeoptimizerData::Iterate(ObjectVisitor* v) { + if (deoptimized_frame_info_ != NULL) { + deoptimized_frame_info_->Iterate(v); + } +} +#endif + + Deoptimizer* Deoptimizer::New(JSFunction* function, BailoutType type, unsigned bailout_id, @@ -70,7 +83,8 @@ Deoptimizer* Deoptimizer::New(JSFunction* function, type, bailout_id, from, - fp_to_sp_delta); + fp_to_sp_delta, + NULL); ASSERT(isolate->deoptimizer_data()->current_ == NULL); isolate->deoptimizer_data()->current_ = deoptimizer; return deoptimizer; @@ -86,6 +100,91 @@ Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { return result; } +#ifdef ENABLE_DEBUGGER_SUPPORT +DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( + JavaScriptFrame* frame, + int frame_index, + Isolate* isolate) { + ASSERT(isolate == Isolate::Current()); + ASSERT(frame->is_optimized()); + ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); + + // Get the function and code from the frame. + JSFunction* function = JSFunction::cast(frame->function()); + Code* code = frame->LookupCode(); + Address code_start_address = code->instruction_start(); + + // Locate the deoptimization point in the code. As we are at a call the + // return address must be at a place in the code with deoptimization support. + int deoptimization_index = Safepoint::kNoDeoptimizationIndex; + // Scope this as the safe point constructor will disallow allocation. + { + SafepointTable table(code); + for (unsigned i = 0; i < table.length(); ++i) { + Address address = code_start_address + table.GetPcOffset(i); + if (address == frame->pc()) { + SafepointEntry safepoint_entry = table.GetEntry(i); + ASSERT(safepoint_entry.deoptimization_index() != + Safepoint::kNoDeoptimizationIndex); + deoptimization_index = safepoint_entry.deoptimization_index(); + break; + } + } + } + ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex); + + // Always use the actual stack slots when calculating the fp to sp + // delta adding two for the function and context. + unsigned stack_slots = code->stack_slots(); + unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize); + + Deoptimizer* deoptimizer = new Deoptimizer(isolate, + function, + Deoptimizer::DEBUGGER, + deoptimization_index, + frame->pc(), + fp_to_sp_delta, + code); + Address tos = frame->fp() - fp_to_sp_delta; + deoptimizer->FillInputFrame(tos, frame); + + // Calculate the output frames. + Deoptimizer::ComputeOutputFrames(deoptimizer); + + // Create the GC safe output frame information and register it for GC + // handling. + ASSERT_LT(frame_index, deoptimizer->output_count()); + DeoptimizedFrameInfo* info = + new DeoptimizedFrameInfo(deoptimizer, frame_index); + isolate->deoptimizer_data()->deoptimized_frame_info_ = info; + + // Get the "simulated" top and size for the requested frame. + Address top = + reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop()); + uint32_t size = deoptimizer->output_[frame_index]->GetFrameSize(); + + // Done with the GC-unsafe frame descriptions. This re-enables allocation. + deoptimizer->DeleteFrameDescriptions(); + + // Allocate a heap number for the doubles belonging to this frame. + deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( + top, size, info); + + // Finished using the deoptimizer instance. + delete deoptimizer; + + return info; +} + + +void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, + Isolate* isolate) { + ASSERT(isolate == Isolate::Current()); + ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); + delete info; + isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; +} +#endif void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, int count, @@ -209,18 +308,24 @@ Deoptimizer::Deoptimizer(Isolate* isolate, BailoutType type, unsigned bailout_id, Address from, - int fp_to_sp_delta) + int fp_to_sp_delta, + Code* optimized_code) : isolate_(isolate), function_(function), bailout_id_(bailout_id), bailout_type_(type), from_(from), fp_to_sp_delta_(fp_to_sp_delta), + input_(NULL), output_count_(0), output_(NULL), deferred_heap_numbers_(0) { if (FLAG_trace_deopt && type != OSR) { - PrintF("**** DEOPT: "); + if (type == DEBUGGER) { + PrintF("**** DEOPT FOR DEBUGGER: "); + } else { + PrintF("**** DEOPT: "); + } function->PrintName(); PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", bailout_id, @@ -248,10 +353,16 @@ Deoptimizer::Deoptimizer(Isolate* isolate, optimized_code_ = function_->code(); ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); ASSERT(!optimized_code_->contains(from)); + } else if (type == DEBUGGER) { + optimized_code_ = optimized_code; + ASSERT(optimized_code_->contains(from)); } ASSERT(HEAP->allow_allocation(false)); unsigned size = ComputeInputFrameSize(); input_ = new(size) FrameDescription(size, function); +#ifdef DEBUG + input_->SetKind(Code::OPTIMIZED_FUNCTION); +#endif } @@ -417,6 +528,7 @@ void Deoptimizer::DoComputeOutputFrames() { void Deoptimizer::MaterializeHeapNumbers() { + ASSERT_NE(DEBUGGER, bailout_type_); for (int i = 0; i < deferred_heap_numbers_.length(); i++) { HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; Handle<Object> num = isolate_->factory()->NewNumber(d.value()); @@ -432,6 +544,47 @@ void Deoptimizer::MaterializeHeapNumbers() { } +#ifdef ENABLE_DEBUGGER_SUPPORT +void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( + Address top, uint32_t size, DeoptimizedFrameInfo* info) { + ASSERT_EQ(DEBUGGER, bailout_type_); + for (int i = 0; i < deferred_heap_numbers_.length(); i++) { + HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; + + // Check of the heap number to materialize actually belong to the frame + // being extracted. + Address slot = d.slot_address(); + if (top <= slot && slot < top + size) { + Handle<Object> num = isolate_->factory()->NewNumber(d.value()); + // Calculate the index with the botton of the expression stack + // at index 0, and the fixed part (including incoming arguments) + // at negative indexes. + int index = static_cast<int>( + info->expression_count_ - (slot - top) / kPointerSize - 1); + if (FLAG_trace_deopt) { + PrintF("Materializing a new heap number %p [%e] in slot %p" + "for stack index %d\n", + reinterpret_cast<void*>(*num), + d.value(), + d.slot_address(), + index); + } + if (index >=0) { + info->SetExpression(index, *num); + } else { + // Calculate parameter index subtracting one for the receiver. + int parameter_index = + index + + static_cast<int>(size) / kPointerSize - + info->expression_count_ - 1; + info->SetParameter(parameter_index, *num); + } + } + } +} +#endif + + void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, int frame_index, unsigned output_offset) { @@ -460,11 +613,13 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, intptr_t input_value = input_->GetRegister(input_reg); if (FLAG_trace_deopt) { PrintF( - " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s\n", + " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ", output_[frame_index]->GetTop() + output_offset, output_offset, input_value, converter.NameOfCPURegister(input_reg)); + reinterpret_cast<Object*>(input_value)->ShortPrint(); + PrintF("\n"); } output_[frame_index]->SetFrameSlot(output_offset, input_value); return; @@ -522,10 +677,12 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, if (FLAG_trace_deopt) { PrintF(" 0x%08" V8PRIxPTR ": ", output_[frame_index]->GetTop() + output_offset); - PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d]\n", + PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d] ", output_offset, input_value, input_offset); + reinterpret_cast<Object*>(input_value)->ShortPrint(); + PrintF("\n"); } output_[frame_index]->SetFrameSlot(output_offset, input_value); return; @@ -901,6 +1058,9 @@ LargeObjectChunk* Deoptimizer::CreateCode(BailoutType type) { ASSERT(desc.reloc_size == 0); LargeObjectChunk* chunk = LargeObjectChunk::New(desc.instr_size, EXECUTABLE); + if (chunk == NULL) { + V8::FatalProcessOutOfMemory("Not enough memory for deoptimization table"); + } memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); return chunk; @@ -969,18 +1129,48 @@ unsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, if (slot_index >= 0) { // Local or spill slots. Skip the fixed part of the frame // including all arguments. - unsigned base = static_cast<unsigned>( - GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction())); + unsigned base = + GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); return base - ((slot_index + 1) * kPointerSize); } else { // Incoming parameter. - unsigned base = static_cast<unsigned>(GetFrameSize() - - deoptimizer->ComputeIncomingArgumentSize(GetFunction())); + unsigned base = GetFrameSize() - + deoptimizer->ComputeIncomingArgumentSize(GetFunction()); return base - ((slot_index + 1) * kPointerSize); } } +int FrameDescription::ComputeParametersCount() { + return function_->shared()->formal_parameter_count(); +} + + +Object* FrameDescription::GetParameter(Deoptimizer* deoptimizer, int index) { + ASSERT_EQ(Code::FUNCTION, kind_); + ASSERT(index >= 0); + ASSERT(index < ComputeParametersCount()); + // The slot indexes for incoming arguments are negative. + unsigned offset = GetOffsetFromSlotIndex(deoptimizer, + index - ComputeParametersCount()); + return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); +} + + +unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) { + ASSERT_EQ(Code::FUNCTION, kind_); + unsigned size = GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); + return size / kPointerSize; +} + + +Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) { + ASSERT_EQ(Code::FUNCTION, kind_); + unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index); + return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); +} + + void TranslationBuffer::Add(int32_t value) { // Encode the sign bit in the least significant bit. bool is_negative = (value < 0); @@ -1104,7 +1294,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) { } -#ifdef OBJECT_PRINT +#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) const char* Translation::StringFor(Opcode opcode) { switch (opcode) { @@ -1253,4 +1443,33 @@ void SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame, } +DeoptimizedFrameInfo::DeoptimizedFrameInfo( + Deoptimizer* deoptimizer, int frame_index) { + FrameDescription* output_frame = deoptimizer->output_[frame_index]; + SetFunction(output_frame->GetFunction()); + expression_count_ = output_frame->GetExpressionCount(deoptimizer); + parameters_count_ = output_frame->ComputeParametersCount(); + parameters_ = new Object*[parameters_count_]; + for (int i = 0; i < parameters_count_; i++) { + SetParameter(i, output_frame->GetParameter(deoptimizer, i)); + } + expression_stack_ = new Object*[expression_count_]; + for (int i = 0; i < expression_count_; i++) { + SetExpression(i, output_frame->GetExpression(deoptimizer, i)); + } +} + + +DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { + delete[] expression_stack_; + delete[] parameters_; +} + +void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { + v->VisitPointer(BitCast<Object**>(&function_)); + v->VisitPointers(parameters_, parameters_ + parameters_count_); + v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); +} + + } } // namespace v8::internal |