43 eager_deoptimization_entry_code_ =
NULL;
44 lazy_deoptimization_entry_code_ =
NULL;
46 deoptimizing_code_list_ =
NULL;
47 #ifdef ENABLE_DEBUGGER_SUPPORT
48 deoptimized_frame_info_ =
NULL;
54 if (eager_deoptimization_entry_code_ !=
NULL) {
55 Isolate::Current()->memory_allocator()->Free(
56 eager_deoptimization_entry_code_);
57 eager_deoptimization_entry_code_ =
NULL;
59 if (lazy_deoptimization_entry_code_ !=
NULL) {
60 Isolate::Current()->memory_allocator()->Free(
61 lazy_deoptimization_entry_code_);
62 lazy_deoptimization_entry_code_ =
NULL;
67 #ifdef ENABLE_DEBUGGER_SUPPORT
68 void DeoptimizerData::Iterate(ObjectVisitor* v) {
69 if (deoptimized_frame_info_ !=
NULL) {
70 deoptimized_frame_info_->Iterate(v);
84 ASSERT(isolate == Isolate::Current());
99 ASSERT(isolate == Isolate::Current());
102 result->DeleteFrameDescriptions();
109 if (jsframe_index == 0)
return 0;
112 while (jsframe_index >= 0) {
120 return frame_index - 1;
124 #ifdef ENABLE_DEBUGGER_SUPPORT
125 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
129 ASSERT(isolate == Isolate::Current());
130 ASSERT(frame->is_optimized());
135 Code* code = frame->LookupCode();
139 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
140 int deoptimization_index = safepoint_entry.deoptimization_index();
141 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
145 unsigned stack_slots = code->stack_slots();
146 unsigned fp_to_sp_delta = ((stack_slots + 2) *
kPointerSize);
151 deoptimization_index,
155 Address tos = frame->fp() - fp_to_sp_delta;
156 deoptimizer->FillInputFrame(tos, frame);
168 bool has_arguments_adaptor =
170 deoptimizer->output_[frame_index - 1]->
GetFrameType() ==
173 int construct_offset = has_arguments_adaptor ? 2 : 1;
174 bool has_construct_stub =
175 frame_index >= construct_offset &&
176 deoptimizer->output_[frame_index - construct_offset]->
GetFrameType() ==
177 StackFrame::CONSTRUCT;
181 has_arguments_adaptor,
187 deoptimizer->output_[
188 has_arguments_adaptor ? (frame_index - 1) : frame_index];
190 uint32_t parameters_size = (info->parameters_count() + 1) *
kPointerSize;
195 uint32_t expressions_size = info->expression_count() *
kPointerSize;
197 deoptimizer->output_[frame_index]->
GetTop());
200 deoptimizer->DeleteFrameDescriptions();
203 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
204 parameters_top, parameters_size, expressions_top, expressions_size, info);
213 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
215 ASSERT(isolate == Isolate::Current());
216 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info);
218 isolate->deoptimizer_data()->deoptimized_frame_info_ =
NULL;
222 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
225 TableEntryGenerator generator(masm, type, count);
226 generator.Generate();
233 if (FLAG_trace_deopt) {
235 reinterpret_cast<intptr_t>(context));
252 if (FLAG_trace_deopt) {
253 PrintF(
"[deoptimize all contexts]\n");
270 Context* context, OptimizedFunctionVisitor* visitor) {
273 ASSERT(context->IsGlobalContext());
275 visitor->EnterContext(context);
278 while (!element->IsUndefined()) {
282 element = element_function->next_function_link();
283 visitor->VisitFunction(element_function);
285 visitor->LeaveContext(context);
290 JSObject*
object, OptimizedFunctionVisitor* visitor) {
293 if (object->IsJSGlobalProxy()) {
295 ASSERT(proto->IsJSGlobalObject());
298 }
else if (object->IsGlobalObject()) {
306 OptimizedFunctionVisitor* visitor) {
310 Object* context = Isolate::Current()->heap()->global_contexts_list();
311 while (!context->IsUndefined()) {
315 if (!global->IsUndefined()) {
324 void Deoptimizer::HandleWeakDeoptimizedCode(
328 RemoveDeoptimizingCode(*node->
code());
330 node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
331 while (node !=
NULL) {
332 ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data));
340 deoptimizer->DoComputeOutputFrames();
344 Deoptimizer::Deoptimizer(
Isolate* isolate,
345 JSFunction*
function,
350 Code* optimized_code)
353 bailout_id_(bailout_id),
356 fp_to_sp_delta_(fp_to_sp_delta),
357 has_alignment_padding_(0),
362 deferred_heap_numbers_(0) {
363 if (FLAG_trace_deopt && type !=
OSR) {
365 PrintF(
"**** DEOPT FOR DEBUGGER: ");
369 function->PrintName();
372 reinterpret_cast<intptr_t>(from),
374 }
else if (FLAG_trace_osr && type ==
OSR) {
376 function->PrintName();
379 reinterpret_cast<intptr_t>(from),
382 function->shared()->increment_deopt_count();
386 optimized_code_ = function_->
code();
387 if (FLAG_trace_deopt && FLAG_code_comments) {
389 const char* last_comment =
NULL;
390 int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
392 for (RelocIterator it(optimized_code_, mask); !it.done(); it.next()) {
393 RelocInfo* info = it.rinfo();
394 if (info->rmode() == RelocInfo::COMMENT) {
395 last_comment =
reinterpret_cast<const char*
>(info->data());
400 if (
id == bailout_id && last_comment !=
NULL) {
401 PrintF(
" %s\n", last_comment);
407 }
else if (type ==
LAZY) {
408 optimized_code_ = FindDeoptimizingCodeFromAddress(from);
410 }
else if (type ==
OSR) {
414 optimized_code_ = function_->
code();
418 optimized_code_ = optimized_code;
422 unsigned size = ComputeInputFrameSize();
433 void Deoptimizer::DeleteFrameDescriptions() {
435 for (
int i = 0; i < output_count_; ++i) {
436 if (output_[i] != input_)
delete output_[i];
447 if (
id >= kNumberOfEntries)
return NULL;
451 if (data->eager_deoptimization_entry_code_ ==
NULL) {
452 data->eager_deoptimization_entry_code_ = CreateCode(type);
454 base = data->eager_deoptimization_entry_code_;
456 if (data->lazy_deoptimization_entry_code_ ==
NULL) {
457 data->lazy_deoptimization_entry_code_ = CreateCode(type);
459 base = data->lazy_deoptimization_entry_code_;
470 base = data->eager_deoptimization_entry_code_;
472 base = data->lazy_deoptimization_entry_code_;
475 addr < base->area_start() ||
477 (kNumberOfEntries * table_entry_size_)) {
481 static_cast<int>(addr - base->
area_start()) % table_entry_size_);
482 return static_cast<int>(addr - base->
area_start()) / table_entry_size_;
494 for (
int i = 0; i < length; i++) {
495 if (data->
AstId(i) == smi_id) {
499 PrintF(
"[couldn't find pc offset for node=%u]\n",
id);
516 while (node !=
NULL) {
526 void Deoptimizer::DoComputeOutputFrames() {
527 if (bailout_type_ ==
OSR) {
528 DoComputeOsrOutputFrame();
534 if (FLAG_trace_deopt) {
536 (bailout_type_ ==
LAZY ?
" (lazy)" :
""),
537 reinterpret_cast<intptr_t>(function_));
539 PrintF(
" @%d]\n", bailout_id_);
544 DeoptimizationInputData* input_data =
546 unsigned node_id = input_data->AstId(bailout_id_)->value();
547 ByteArray* translations = input_data->TranslationByteArray();
548 unsigned translation_index =
549 input_data->TranslationIndex(bailout_id_)->value();
552 TranslationIterator iterator(translations, translation_index);
555 ASSERT(Translation::BEGIN == opcode);
559 int count = iterator.Next();
563 for (
int i = 0; i < count; ++i) {
566 output_count_ = count;
569 for (
int i = 0; i < count; ++i) {
574 case Translation::JS_FRAME:
575 DoComputeJSFrame(&iterator, i);
578 case Translation::ARGUMENTS_ADAPTOR_FRAME:
579 DoComputeArgumentsAdaptorFrame(&iterator, i);
581 case Translation::CONSTRUCT_STUB_FRAME:
582 DoComputeConstructStubFrame(&iterator, i);
591 if (FLAG_trace_deopt) {
592 double ms =
static_cast<double>(
OS::Ticks() - start) / 1000;
593 int index = output_count_ - 1;
594 JSFunction*
function = output_[index]->
GetFunction();
596 reinterpret_cast<intptr_t>(
function));
597 function->PrintName();
601 output_[index]->GetPc(),
603 static_cast<FullCodeGenerator::State>(
604 output_[index]->GetState()->value())),
605 has_alignment_padding_ ?
"with padding" :
"no padding",
613 for (
int i = 0; i < deferred_heap_numbers_.length(); i++) {
614 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
616 if (FLAG_trace_deopt) {
617 PrintF(
"Materializing a new heap number %p [%e] in slot %p\n",
618 reinterpret_cast<void*>(*num),
628 #ifdef ENABLE_DEBUGGER_SUPPORT
629 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
631 uint32_t parameters_size,
633 uint32_t expressions_size,
634 DeoptimizedFrameInfo* info) {
636 Address parameters_bottom = parameters_top + parameters_size;
637 Address expressions_bottom = expressions_top + expressions_size;
638 for (
int i = 0; i < deferred_heap_numbers_.length(); i++) {
639 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
643 Address slot = d.slot_address();
644 if (parameters_top <= slot && slot < parameters_bottom) {
647 int index = (info->parameters_count() - 1) -
650 if (FLAG_trace_deopt) {
651 PrintF(
"Materializing a new heap number %p [%e] in slot %p"
652 "for parameter slot #%d\n",
653 reinterpret_cast<void*>(*num),
659 info->SetParameter(index, *num);
660 }
else if (expressions_top <= slot && slot < expressions_bottom) {
663 int index = info->expression_count() - 1 -
664 static_cast<int>(slot - expressions_top) /
kPointerSize;
666 if (FLAG_trace_deopt) {
667 PrintF(
"Materializing a new heap number %p [%e] in slot %p"
668 "for expression slot #%d\n",
669 reinterpret_cast<void*>(*num),
675 info->SetExpression(index, *num);
682 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
684 unsigned output_offset) {
687 const intptr_t kPlaceholder =
reinterpret_cast<intptr_t
>(
Smi::FromInt(0));
692 while (opcode == Translation::DUPLICATE) {
694 iterator->Skip(Translation::NumberOfOperandsFor(opcode));
699 case Translation::BEGIN:
700 case Translation::JS_FRAME:
701 case Translation::ARGUMENTS_ADAPTOR_FRAME:
702 case Translation::CONSTRUCT_STUB_FRAME:
703 case Translation::DUPLICATE:
708 int input_reg = iterator->Next();
709 intptr_t input_value = input_->
GetRegister(input_reg);
710 if (FLAG_trace_deopt) {
713 output_[frame_index]->GetTop() + output_offset,
717 reinterpret_cast<Object*
>(input_value)->ShortPrint();
720 output_[frame_index]->
SetFrameSlot(output_offset, input_value);
724 case Translation::INT32_REGISTER: {
725 int input_reg = iterator->Next();
728 if (FLAG_trace_deopt) {
730 " 0x%08" V8PRIxPTR
": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
731 output_[frame_index]->GetTop() + output_offset,
735 is_smi ?
"smi" :
"heap number");
738 intptr_t tagged_value =
739 reinterpret_cast<intptr_t
>(
Smi::FromInt(static_cast<int>(value)));
740 output_[frame_index]->
SetFrameSlot(output_offset, tagged_value);
744 AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
745 static_cast<double>(static_cast<int32_t>(value)));
746 output_[frame_index]->
SetFrameSlot(output_offset, kPlaceholder);
751 case Translation::DOUBLE_REGISTER: {
752 int input_reg = iterator->Next();
754 if (FLAG_trace_deopt) {
755 PrintF(
" 0x%08" V8PRIxPTR
": [top + %d] <- %e ; %s\n",
756 output_[frame_index]->GetTop() + output_offset,
763 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
764 output_[frame_index]->
SetFrameSlot(output_offset, kPlaceholder);
768 case Translation::STACK_SLOT: {
769 int input_slot_index = iterator->Next();
772 intptr_t input_value = input_->
GetFrameSlot(input_offset);
773 if (FLAG_trace_deopt) {
774 PrintF(
" 0x%08" V8PRIxPTR
": ",
775 output_[frame_index]->GetTop() + output_offset);
776 PrintF(
"[top + %d] <- 0x%08" V8PRIxPTR
" ; [sp + %d] ",
780 reinterpret_cast<Object*
>(input_value)->ShortPrint();
783 output_[frame_index]->
SetFrameSlot(output_offset, input_value);
787 case Translation::INT32_STACK_SLOT: {
788 int input_slot_index = iterator->Next();
789 unsigned input_offset =
793 if (FLAG_trace_deopt) {
794 PrintF(
" 0x%08" V8PRIxPTR
": ",
795 output_[frame_index]->GetTop() + output_offset);
796 PrintF(
"[top + %d] <- %" V8PRIdPTR
" ; [sp + %d] (%s)\n",
800 is_smi ?
"smi" :
"heap number");
803 intptr_t tagged_value =
804 reinterpret_cast<intptr_t
>(
Smi::FromInt(static_cast<int>(value)));
805 output_[frame_index]->
SetFrameSlot(output_offset, tagged_value);
809 AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
810 static_cast<double>(static_cast<int32_t>(value)));
811 output_[frame_index]->
SetFrameSlot(output_offset, kPlaceholder);
816 case Translation::DOUBLE_STACK_SLOT: {
817 int input_slot_index = iterator->Next();
818 unsigned input_offset =
821 if (FLAG_trace_deopt) {
822 PrintF(
" 0x%08" V8PRIxPTR
": [top + %d] <- %e ; [sp + %d]\n",
823 output_[frame_index]->GetTop() + output_offset,
830 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
831 output_[frame_index]->
SetFrameSlot(output_offset, kPlaceholder);
835 case Translation::LITERAL: {
836 Object* literal = ComputeLiteral(iterator->Next());
837 if (FLAG_trace_deopt) {
838 PrintF(
" 0x%08" V8PRIxPTR
": [top + %d] <- ",
839 output_[frame_index]->GetTop() + output_offset,
841 literal->ShortPrint();
844 intptr_t value =
reinterpret_cast<intptr_t
>(literal);
845 output_[frame_index]->
SetFrameSlot(output_offset, value);
849 case Translation::ARGUMENTS_OBJECT: {
852 if (FLAG_trace_deopt) {
853 PrintF(
" 0x%08" V8PRIxPTR
": [top + %d] <- ",
854 output_[frame_index]->GetTop() + output_offset,
856 isolate_->
heap()->arguments_marker()->ShortPrint();
857 PrintF(
" ; arguments object\n");
859 intptr_t value =
reinterpret_cast<intptr_t
>(
860 isolate_->
heap()->arguments_marker());
861 output_[frame_index]->
SetFrameSlot(output_offset, value);
868 bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
875 uintptr_t input_value = input_->
GetFrameSlot(*input_offset);
876 Object* input_object =
reinterpret_cast<Object*
>(input_value);
880 bool duplicate = (opcode == Translation::DUPLICATE);
886 case Translation::BEGIN:
887 case Translation::JS_FRAME:
888 case Translation::ARGUMENTS_ADAPTOR_FRAME:
889 case Translation::CONSTRUCT_STUB_FRAME:
890 case Translation::DUPLICATE:
895 int output_reg = iterator->Next();
896 if (FLAG_trace_osr) {
897 PrintF(
" %s <- 0x%08" V8PRIxPTR
" ; [sp + %d]\n",
902 output->SetRegister(output_reg, input_value);
906 case Translation::INT32_REGISTER: {
908 if (!input_object->IsNumber())
return false;
910 int output_reg = iterator->Next();
911 int int32_value = input_object->IsSmi()
913 :
FastD2I(input_object->Number());
915 if (!input_object->IsSmi() &&
916 FastI2D(int32_value) != input_object->Number()) {
917 if (FLAG_trace_osr) {
918 PrintF(
"**** %g could not be converted to int32 ****\n",
919 input_object->Number());
923 if (FLAG_trace_osr) {
924 PrintF(
" %s <- %d (int32) ; [sp + %d]\n",
929 output->SetRegister(output_reg, int32_value);
933 case Translation::DOUBLE_REGISTER: {
935 if (!input_object->IsNumber())
return false;
937 int output_reg = iterator->Next();
938 double double_value = input_object->Number();
939 if (FLAG_trace_osr) {
940 PrintF(
" %s <- %g (double) ; [sp + %d]\n",
945 output->SetDoubleRegister(output_reg, double_value);
949 case Translation::STACK_SLOT: {
950 int output_index = iterator->Next();
951 unsigned output_offset =
952 output->GetOffsetFromSlotIndex(output_index);
953 if (FLAG_trace_osr) {
954 PrintF(
" [sp + %d] <- 0x%08" V8PRIxPTR
" ; [sp + %d] ",
958 reinterpret_cast<Object*
>(input_value)->ShortPrint();
961 output->SetFrameSlot(output_offset, input_value);
965 case Translation::INT32_STACK_SLOT: {
967 if (!input_object->IsNumber())
return false;
969 int output_index = iterator->Next();
970 unsigned output_offset =
971 output->GetOffsetFromSlotIndex(output_index);
972 int int32_value = input_object->IsSmi()
976 if (!input_object->IsSmi() &&
977 FastI2D(int32_value) != input_object->Number()) {
978 if (FLAG_trace_osr) {
979 PrintF(
"**** %g could not be converted to int32 ****\n",
980 input_object->Number());
984 if (FLAG_trace_osr) {
985 PrintF(
" [sp + %d] <- %d (int32) ; [sp + %d]\n",
990 output->SetFrameSlot(output_offset, int32_value);
994 case Translation::DOUBLE_STACK_SLOT: {
999 if (!input_object->IsNumber())
return false;
1001 int output_index = iterator->Next();
1002 unsigned output_offset =
1003 output->GetOffsetFromSlotIndex(output_index);
1004 double double_value = input_object->Number();
1005 uint64_t int_value = BitCast<uint64_t, double>(double_value);
1008 if (FLAG_trace_osr) {
1009 PrintF(
" [sp + %d] <- 0x%08x (upper bits of %g) ; [sp + %d]\n",
1010 output_offset + kUpperOffset,
1014 PrintF(
" [sp + %d] <- 0x%08x (lower bits of %g) ; [sp + %d]\n",
1015 output_offset + kLowerOffset,
1020 output->SetFrameSlot(output_offset + kLowerOffset, lower);
1021 output->SetFrameSlot(output_offset + kUpperOffset, upper);
1025 case Translation::LITERAL: {
1031 case Translation::ARGUMENTS_OBJECT: {
1048 Code* replacement_code) {
1056 for (uint32_t i = 0; i < table_length; ++i) {
1063 stack_check_cursor += 2 *
kIntSize;
1070 Code* replacement_code) {
1078 for (uint32_t i = 0; i < table_length; ++i) {
1085 stack_check_cursor += 2 *
kIntSize;
1090 unsigned Deoptimizer::ComputeInputFrameSize()
const {
1091 unsigned fixed_size = ComputeFixedSize(function_);
1094 unsigned result = fixed_size + fp_to_sp_delta_ - (2 *
kPointerSize);
1096 if (bailout_type_ ==
OSR) {
1102 unsigned stack_slots = optimized_code_->
stack_slots();
1103 unsigned outgoing_size = ComputeOutgoingArgumentSize();
1111 unsigned Deoptimizer::ComputeFixedSize(JSFunction*
function)
const {
1114 return ComputeIncomingArgumentSize(
function) +
1119 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction*
function)
const {
1122 unsigned arguments =
function->shared()->formal_parameter_count() + 1;
1127 unsigned Deoptimizer::ComputeOutgoingArgumentSize()
const {
1129 optimized_code_->deoptimization_data());
1130 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
1135 Object* Deoptimizer::ComputeLiteral(
int index)
const {
1137 optimized_code_->deoptimization_data());
1138 FixedArray* literals = data->LiteralArray();
1139 return literals->
get(index);
1143 void Deoptimizer::AddDoubleValue(intptr_t slot_address,
1145 HeapNumberMaterializationDescriptor value_desc(
1146 reinterpret_cast<Address>(slot_address), value);
1147 deferred_heap_numbers_.
Add(value_desc);
1151 MemoryChunk* Deoptimizer::CreateCode(BailoutType type) {
1158 MacroAssembler masm(Isolate::Current(),
NULL, 16 *
KB);
1159 masm.set_emit_debug_code(
false);
1160 GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type);
1162 masm.GetCode(&desc);
1163 ASSERT(desc.reloc_size == 0);
1165 MemoryChunk* chunk =
1166 Isolate::Current()->memory_allocator()->AllocateChunk(desc.instr_size,
1169 ASSERT(chunk->area_size() >= desc.instr_size);
1170 if (chunk ==
NULL) {
1173 memcpy(chunk->area_start(), desc.buffer, desc.instr_size);
1179 Code* Deoptimizer::FindDeoptimizingCodeFromAddress(
Address addr) {
1181 Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
1182 while (node !=
NULL) {
1183 if (node->code()->contains(addr))
return *node->code();
1184 node = node->next();
1190 void Deoptimizer::RemoveDeoptimizingCode(Code* code) {
1191 DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
1192 ASSERT(data->deoptimizing_code_list_ !=
NULL);
1196 while (current !=
NULL) {
1197 if (*current->code() == code) {
1200 data->deoptimizing_code_list_ = current->next();
1202 prev->set_next(current->next());
1209 current = current->next();
1218 JSFunction*
function)
1219 : frame_size_(frame_size),
1220 function_(function),
1224 context_(kZapUint32) {
1231 for (
unsigned o = 0; o < frame_size; o +=
kPointerSize) {
1237 int FrameDescription::ComputeFixedSize() {
1244 if (slot_index >= 0) {
1260 case StackFrame::JAVA_SCRIPT:
1261 return function_->shared()->formal_parameter_count();
1265 return reinterpret_cast<Smi*
>(*GetFrameSlotPointer(0))->value();
1279 return reinterpret_cast<Object*
>(*GetFrameSlotPointer(offset));
1284 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_);
1291 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_);
1293 return reinterpret_cast<Object*
>(*GetFrameSlotPointer(offset));
1297 void TranslationBuffer::Add(
int32_t value,
Zone* zone) {
1299 bool is_negative = (value < 0);
1300 uint32_t bits = ((is_negative ? -value : value) << 1) |
1301 static_cast<int32_t>(is_negative);
1305 uint32_t next = bits >> 7;
1306 contents_.Add(((bits << 1) & 0xFF) | (next != 0), zone);
1308 }
while (bits != 0);
1312 int32_t TranslationIterator::Next() {
1316 for (
int i = 0;
true; i += 7) {
1318 uint8_t next =
buffer_->get(index_++);
1319 bits |= (next >> 1) << i;
1320 if ((next & 1) == 0)
break;
1323 bool is_negative = (bits & 1) == 1;
1325 return is_negative ? -result : result;
1329 Handle<ByteArray> TranslationBuffer::CreateByteArray() {
1330 int length = contents_.length();
1331 Handle<ByteArray> result =
1332 Isolate::Current()->factory()->NewByteArray(length,
TENURED);
1333 memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length);
1338 void Translation::BeginConstructStubFrame(
int literal_id,
unsigned height) {
1339 buffer_->Add(CONSTRUCT_STUB_FRAME, zone());
1340 buffer_->Add(literal_id, zone());
1345 void Translation::BeginArgumentsAdaptorFrame(
int literal_id,
unsigned height) {
1346 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone());
1347 buffer_->Add(literal_id, zone());
1352 void Translation::BeginJSFrame(
int node_id,
int literal_id,
unsigned height) {
1353 buffer_->Add(JS_FRAME, zone());
1354 buffer_->Add(node_id, zone());
1355 buffer_->Add(literal_id, zone());
1360 void Translation::StoreRegister(Register reg) {
1362 buffer_->Add(reg.code(), zone());
1366 void Translation::StoreInt32Register(Register reg) {
1367 buffer_->Add(INT32_REGISTER, zone());
1368 buffer_->Add(reg.code(), zone());
1373 buffer_->Add(DOUBLE_REGISTER, zone());
1378 void Translation::StoreStackSlot(
int index) {
1379 buffer_->Add(STACK_SLOT, zone());
1384 void Translation::StoreInt32StackSlot(
int index) {
1385 buffer_->Add(INT32_STACK_SLOT, zone());
1390 void Translation::StoreDoubleStackSlot(
int index) {
1391 buffer_->Add(DOUBLE_STACK_SLOT, zone());
1396 void Translation::StoreLiteral(
int literal_id) {
1397 buffer_->Add(LITERAL, zone());
1398 buffer_->Add(literal_id, zone());
1402 void Translation::StoreArgumentsObject() {
1403 buffer_->Add(ARGUMENTS_OBJECT, zone());
1407 void Translation::MarkDuplicate() {
1408 buffer_->Add(DUPLICATE, zone());
1412 int Translation::NumberOfOperandsFor(
Opcode opcode) {
1414 case ARGUMENTS_OBJECT:
1418 case INT32_REGISTER:
1419 case DOUBLE_REGISTER:
1421 case INT32_STACK_SLOT:
1422 case DOUBLE_STACK_SLOT:
1426 case ARGUMENTS_ADAPTOR_FRAME:
1427 case CONSTRUCT_STUB_FRAME:
1437 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
1439 const char* Translation::StringFor(
Opcode opcode) {
1445 case ARGUMENTS_ADAPTOR_FRAME:
1446 return "ARGUMENTS_ADAPTOR_FRAME";
1447 case CONSTRUCT_STUB_FRAME:
1448 return "CONSTRUCT_STUB_FRAME";
1451 case INT32_REGISTER:
1452 return "INT32_REGISTER";
1453 case DOUBLE_REGISTER:
1454 return "DOUBLE_REGISTER";
1456 return "STACK_SLOT";
1457 case INT32_STACK_SLOT:
1458 return "INT32_STACK_SLOT";
1459 case DOUBLE_STACK_SLOT:
1460 return "DOUBLE_STACK_SLOT";
1463 case ARGUMENTS_OBJECT:
1464 return "ARGUMENTS_OBJECT";
1476 GlobalHandles* global_handles = Isolate::Current()->global_handles();
1479 global_handles->
MakeWeak(reinterpret_cast<Object**>(code_.location()),
1481 Deoptimizer::HandleWeakDeoptimizedCode);
1486 GlobalHandles* global_handles = Isolate::Current()->global_handles();
1487 global_handles->
Destroy(reinterpret_cast<Object**>(code_.location()));
1494 SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator,
1501 case Translation::BEGIN:
1502 case Translation::JS_FRAME:
1503 case Translation::ARGUMENTS_ADAPTOR_FRAME:
1504 case Translation::CONSTRUCT_STUB_FRAME:
1508 case Translation::ARGUMENTS_OBJECT:
1513 case Translation::INT32_REGISTER:
1514 case Translation::DOUBLE_REGISTER:
1515 case Translation::DUPLICATE:
1521 case Translation::STACK_SLOT: {
1522 int slot_index = iterator->Next();
1523 Address slot_addr = SlotAddress(frame, slot_index);
1524 return SlotRef(slot_addr, SlotRef::TAGGED);
1527 case Translation::INT32_STACK_SLOT: {
1528 int slot_index = iterator->Next();
1529 Address slot_addr = SlotAddress(frame, slot_index);
1530 return SlotRef(slot_addr, SlotRef::INT32);
1533 case Translation::DOUBLE_STACK_SLOT: {
1534 int slot_index = iterator->Next();
1535 Address slot_addr = SlotAddress(frame, slot_index);
1536 return SlotRef(slot_addr, SlotRef::DOUBLE);
1539 case Translation::LITERAL: {
1540 int literal_index = iterator->Next();
1541 return SlotRef(data->LiteralArray()->
get(literal_index));
1550 void SlotRef::ComputeSlotsForArguments(Vector<SlotRef>* args_slots,
1551 TranslationIterator* it,
1552 DeoptimizationInputData* data,
1553 JavaScriptFrame* frame) {
1557 it->Skip(Translation::NumberOfOperandsFor(
1558 static_cast<Translation::Opcode>(it->Next())));
1561 for (
int i = 0; i < args_slots->length(); ++i) {
1562 (*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame);
1567 Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments(
1568 JavaScriptFrame* frame,
1569 int inlined_jsframe_index,
1571 AssertNoAllocation no_gc;
1573 DeoptimizationInputData* data =
1574 static_cast<OptimizedFrame*
>(frame)->GetDeoptimizationData(&deopt_index);
1575 TranslationIterator it(data->TranslationByteArray(),
1576 data->TranslationIndex(deopt_index)->value());
1578 ASSERT(opcode == Translation::BEGIN);
1580 int jsframe_count = it.Next();
1582 ASSERT(jsframe_count > inlined_jsframe_index);
1583 int jsframes_to_skip = inlined_jsframe_index;
1586 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) {
1587 if (jsframes_to_skip == 0) {
1588 ASSERT(Translation::NumberOfOperandsFor(opcode) == 2);
1591 int height = it.Next();
1595 Vector<SlotRef> args_slots =
1597 ComputeSlotsForArguments(&args_slots, &it, data, frame);
1600 }
else if (opcode == Translation::JS_FRAME) {
1601 if (jsframes_to_skip == 0) {
1603 it.Skip(Translation::NumberOfOperandsFor(opcode));
1609 Vector<SlotRef> args_slots =
1611 ComputeSlotsForArguments(&args_slots, &it, data, frame);
1618 it.Skip(Translation::NumberOfOperandsFor(opcode));
1622 return Vector<SlotRef>();
1625 #ifdef ENABLE_DEBUGGER_SUPPORT
1627 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
1629 bool has_arguments_adaptor,
1630 bool has_construct_stub) {
1631 FrameDescription* output_frame = deoptimizer->output_[frame_index];
1632 function_ = output_frame->GetFunction();
1633 has_construct_stub_ = has_construct_stub;
1634 expression_count_ = output_frame->GetExpressionCount();
1635 expression_stack_ =
new Object*[expression_count_];
1638 Code* code =
Code::cast(Isolate::Current()->heap()->FindCodeObject(pc));
1639 source_position_ = code->SourcePosition(pc);
1641 for (
int i = 0; i < expression_count_; i++) {
1642 SetExpression(i, output_frame->GetExpression(i));
1645 if (has_arguments_adaptor) {
1646 output_frame = deoptimizer->output_[frame_index - 1];
1650 parameters_count_ = output_frame->ComputeParametersCount();
1651 parameters_ =
new Object*[parameters_count_];
1652 for (
int i = 0; i < parameters_count_; i++) {
1653 SetParameter(i, output_frame->GetParameter(i));
1658 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
1659 delete[] expression_stack_;
1660 delete[] parameters_;
1664 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
1665 v->VisitPointer(BitCast<Object**>(&function_));
1666 v->VisitPointers(parameters_, parameters_ + parameters_count_);
1667 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
1670 #endif // ENABLE_DEBUGGER_SUPPORT
DeoptimizingCodeListNode * next() const
void Destroy(Object **location)
Object * function() const
static Object *& Object_at(Address addr)
void PrintF(const char *format,...)
Handle< Code > code() const
void SourceCodePrint(StringStream *accumulator, int max_length)
static Smi * FromInt(int value)
unsigned stack_check_table_offset()
unsigned GetOffsetFromSlotIndex(int slot_index)
static void RevertStackCheckCode(Code *unoptimized_code, Code *check_code, Code *replacement_code)
void SetFrameSlot(unsigned offset, intptr_t value)
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kThisPropertyAssignmentsOffset kNeedsAccessCheckBit kIsExpressionBit kHasOnlySimpleThisPropertyAssignments kUsesArguments formal_parameter_count
static void ComputeOutputFrames(Deoptimizer *deoptimizer)
static Handle< T > cast(Handle< S > that)
static const int kNoNumber
virtual void EnterContext(Context *context)
#define ASSERT(condition)
static void DeoptimizeFunction(JSFunction *function)
static Context * cast(Object *context)
static void DeoptimizeAll()
double GetDoubleRegister(unsigned n) const
Handle< Object > NewNumber(double value, PretenureFlag pretenure=NOT_TENURED)
void SetFrameType(StackFrame::Type type)
StringInputBuffer *const buffer_
DeoptimizingCodeListNode(Code *code)
virtual void VisitFunction(JSFunction *function)
static Code * cast(Object *obj)
static Smi * cast(Object *object)
static const char * AllocationIndexToString(int index)
static const int kNumRegisters
virtual void LeaveContext(Context *context)
void ClearOptimizedFunctions()
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
int ComputeParametersCount()
JSFunction * GetFunction() const
static void DeoptimizeGlobalObject(JSObject *object)
DwVfpRegister DoubleRegister
virtual const char * NameOfCPURegister(int reg) const
Handle< Object > Create(Object *value)
static bool IsValid(intptr_t value)
Smi * PcAndState(int index)
byte * instruction_start()
Object * OptimizedFunctionsListHead()
void SetRegister(unsigned n, intptr_t value)
friend class DeoptimizingCodeListNode
static int GetDeoptimizedCodeCount(Isolate *isolate)
unsigned GetExpressionCount()
static const char * State2String(State state)
static int GetOutputInfo(DeoptimizationOutputData *data, unsigned node_id, SharedFunctionInfo *shared)
static const int kFixedFrameSize
static void PatchStackCheckCode(Code *unoptimized_code, Code *check_code, Code *replacement_code)
~DeoptimizingCodeListNode()
static Vector< T > New(int length)
DeoptimizerData * deoptimizer_data()
uint32_t GetFrameSize() const
static void VisitAllOptimizedFunctionsForContext(Context *context, OptimizedFunctionVisitor *visitor)
#define ASSERT_LT(v1, v2)
static void RevertStackCheckCodeAt(Code *unoptimized_code, Address pc_after, Code *check_code, Code *replacement_code)
int32_t DoubleToInt32(double x)
intptr_t GetFrameSlot(unsigned offset)
friend class DeoptimizedFrameInfo
void MaterializeHeapNumbers()
static Address GetDeoptimizationEntry(int id, BailoutType type)
static int ToAllocationIndex(DwVfpRegister reg)
static Deoptimizer * Grab(Isolate *isolate)
static const int kNotDeoptimizationEntry
#define ASSERT_EQ(v1, v2)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
friend class FrameDescription
StackFrame::Type GetFrameType() const
#define ASSERT_NE(v1, v2)
double GetDoubleFrameSlot(unsigned offset)
FrameDescription(uint32_t frame_size, JSFunction *function)
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor *visitor)
static uint32_t & uint32_at(Address addr)
#define RUNTIME_ENTRY(name, nargs, ressize)
static void VisitAllOptimizedFunctionsForGlobalObject(JSObject *object, OptimizedFunctionVisitor *visitor)
int ConvertJSFrameIndexToFrameIndex(int jsframe_index)
static void FlushICache(void *start, size_t size)
void MakeWeak(Object **location, void *parameter, WeakReferenceCallback callback)
intptr_t GetRegister(unsigned n) const
static GlobalObject * cast(Object *obj)
SmartArrayPointer< const char > ToCString() const
int jsframe_count() const
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
static int GetDeoptimizationId(Address addr, BailoutType type)
static JSObject * cast(Object *obj)
static void PatchStackCheckCodeAt(Code *unoptimized_code, Address pc_after, Code *check_code, Code *replacement_code)
static Deoptimizer * New(JSFunction *function, BailoutType type, unsigned bailout_id, Address from, int fp_to_sp_delta, Isolate *isolate)
static int input_offset()
Object * GetExpression(int index)
Object * GetParameter(int index)
static JSFunction * cast(Object *obj)