| OLD | NEW | 
|    1 // Copyright 2011 the V8 project authors. All rights reserved. |    1 // Copyright 2011 the V8 project authors. All rights reserved. | 
|    2 // Redistribution and use in source and binary forms, with or without |    2 // Redistribution and use in source and binary forms, with or without | 
|    3 // modification, are permitted provided that the following conditions are |    3 // modification, are permitted provided that the following conditions are | 
|    4 // met: |    4 // met: | 
|    5 // |    5 // | 
|    6 //     * Redistributions of source code must retain the above copyright |    6 //     * Redistributions of source code must retain the above copyright | 
|    7 //       notice, this list of conditions and the following disclaimer. |    7 //       notice, this list of conditions and the following disclaimer. | 
|    8 //     * Redistributions in binary form must reproduce the above |    8 //     * Redistributions in binary form must reproduce the above | 
|    9 //       copyright notice, this list of conditions and the following |    9 //       copyright notice, this list of conditions and the following | 
|   10 //       disclaimer in the documentation and/or other materials provided |   10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  217   // We will patch away the branch so the code is: |  217   // We will patch away the branch so the code is: | 
|  218   // |  218   // | 
|  219   //     cmp rsp, <limit>  ;; Not changed |  219   //     cmp rsp, <limit>  ;; Not changed | 
|  220   //     nop |  220   //     nop | 
|  221   //     nop |  221   //     nop | 
|  222   //     call <on-stack replacment> |  222   //     call <on-stack replacment> | 
|  223   //     test rax, <loop nesting depth> |  223   //     test rax, <loop nesting depth> | 
|  224   // ok: |  224   // ok: | 
|  225   // |  225   // | 
|  226   ASSERT(*(call_target_address - 3) == 0x73 &&  // jae |  226   ASSERT(*(call_target_address - 3) == 0x73 &&  // jae | 
|  227          *(call_target_address - 2) == 0x05 &&  // offset |  227          *(call_target_address - 2) == 0x07 &&  // offset | 
|  228          *(call_target_address - 1) == 0xe8);   // call |  228          *(call_target_address - 1) == 0xe8);   // call | 
|  229   *(call_target_address - 3) = 0x90;  // nop |  229   *(call_target_address - 3) = 0x90;  // nop | 
|  230   *(call_target_address - 2) = 0x90;  // nop |  230   *(call_target_address - 2) = 0x90;  // nop | 
|  231   Assembler::set_target_address_at(call_target_address, |  231   Assembler::set_target_address_at(call_target_address, | 
|  232                                    replacement_code->entry()); |  232                                    replacement_code->entry()); | 
|  233 } |  233 } | 
|  234  |  234  | 
|  235  |  235  | 
|  236 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after, |  236 void Deoptimizer::RevertStackCheckCodeAt(Address pc_after, | 
|  237                                          Code* check_code, |  237                                          Code* check_code, | 
|  238                                          Code* replacement_code) { |  238                                          Code* replacement_code) { | 
|  239   Address call_target_address = pc_after - kIntSize; |  239   Address call_target_address = pc_after - kIntSize; | 
|  240   ASSERT(replacement_code->entry() == |  240   ASSERT(replacement_code->entry() == | 
|  241          Assembler::target_address_at(call_target_address)); |  241          Assembler::target_address_at(call_target_address)); | 
|  242   // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to |  242   // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to | 
|  243   // restore the conditional branch. |  243   // restore the conditional branch. | 
|  244   ASSERT(*(call_target_address - 3) == 0x90 &&  // nop |  244   ASSERT(*(call_target_address - 3) == 0x90 &&  // nop | 
|  245          *(call_target_address - 2) == 0x90 &&  // nop |  245          *(call_target_address - 2) == 0x90 &&  // nop | 
|  246          *(call_target_address - 1) == 0xe8);   // call |  246          *(call_target_address - 1) == 0xe8);   // call | 
|  247   *(call_target_address - 3) = 0x73;  // jae |  247   *(call_target_address - 3) = 0x73;  // jae | 
|  248   *(call_target_address - 2) = 0x05;  // offset |  248   *(call_target_address - 2) = 0x07;  // offset | 
|  249   Assembler::set_target_address_at(call_target_address, |  249   Assembler::set_target_address_at(call_target_address, | 
|  250                                    check_code->entry()); |  250                                    check_code->entry()); | 
|  251 } |  251 } | 
|  252  |  252  | 
|  253  |  253  | 
|  254 void Deoptimizer::DoComputeOsrOutputFrame() { |  254 static int LookupBailoutId(DeoptimizationInputData* data, unsigned ast_id) { | 
|  255   UNIMPLEMENTED(); |  255   ByteArray* translations = data->TranslationByteArray(); | 
 |  256   int length = data->DeoptCount(); | 
 |  257   for (int i = 0; i < length; i++) { | 
 |  258     if (static_cast<unsigned>(data->AstId(i)->value()) == ast_id) { | 
 |  259       TranslationIterator it(translations,  data->TranslationIndex(i)->value()); | 
 |  260       int value = it.Next(); | 
 |  261       ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value)); | 
 |  262       // Read the number of frames. | 
 |  263       value = it.Next(); | 
 |  264       if (value == 1) return i; | 
 |  265     } | 
 |  266   } | 
 |  267   UNREACHABLE(); | 
 |  268   return -1; | 
|  256 } |  269 } | 
|  257  |  270  | 
|  258  |  271  | 
 |  272 void Deoptimizer::DoComputeOsrOutputFrame() { | 
 |  273   DeoptimizationInputData* data = DeoptimizationInputData::cast( | 
 |  274       optimized_code_->deoptimization_data()); | 
 |  275   unsigned ast_id = data->OsrAstId()->value(); | 
 |  276   // TODO(kasperl): This should not be the bailout_id_. It should be | 
 |  277   // the ast id. Confusing. | 
 |  278   ASSERT(bailout_id_ == ast_id); | 
 |  279  | 
 |  280   int bailout_id = LookupBailoutId(data, ast_id); | 
 |  281   unsigned translation_index = data->TranslationIndex(bailout_id)->value(); | 
 |  282   ByteArray* translations = data->TranslationByteArray(); | 
 |  283  | 
 |  284   TranslationIterator iterator(translations, translation_index); | 
 |  285   Translation::Opcode opcode = | 
 |  286       static_cast<Translation::Opcode>(iterator.Next()); | 
 |  287   ASSERT(Translation::BEGIN == opcode); | 
 |  288   USE(opcode); | 
 |  289   int count = iterator.Next(); | 
 |  290   ASSERT(count == 1); | 
 |  291   USE(count); | 
 |  292  | 
 |  293   opcode = static_cast<Translation::Opcode>(iterator.Next()); | 
 |  294   USE(opcode); | 
 |  295   ASSERT(Translation::FRAME == opcode); | 
 |  296   unsigned node_id = iterator.Next(); | 
 |  297   USE(node_id); | 
 |  298   ASSERT(node_id == ast_id); | 
 |  299   JSFunction* function = JSFunction::cast(ComputeLiteral(iterator.Next())); | 
 |  300   USE(function); | 
 |  301   ASSERT(function == function_); | 
 |  302   unsigned height = iterator.Next(); | 
 |  303   unsigned height_in_bytes = height * kPointerSize; | 
 |  304   USE(height_in_bytes); | 
 |  305  | 
 |  306   unsigned fixed_size = ComputeFixedSize(function_); | 
 |  307   unsigned input_frame_size = input_->GetFrameSize(); | 
 |  308   ASSERT(fixed_size + height_in_bytes == input_frame_size); | 
 |  309  | 
 |  310   unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; | 
 |  311   unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); | 
 |  312   unsigned outgoing_size = outgoing_height * kPointerSize; | 
 |  313   unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; | 
 |  314   ASSERT(outgoing_size == 0);  // OSR does not happen in the middle of a call. | 
 |  315  | 
 |  316   if (FLAG_trace_osr) { | 
 |  317     PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", | 
 |  318            reinterpret_cast<intptr_t>(function_)); | 
 |  319     function_->PrintName(); | 
 |  320     PrintF(" => node=%u, frame=%d->%d]\n", | 
 |  321            ast_id, | 
 |  322            input_frame_size, | 
 |  323            output_frame_size); | 
 |  324   } | 
 |  325  | 
 |  326   // There's only one output frame in the OSR case. | 
 |  327   output_count_ = 1; | 
 |  328   output_ = new FrameDescription*[1]; | 
 |  329   output_[0] = new(output_frame_size) FrameDescription( | 
 |  330       output_frame_size, function_); | 
 |  331  | 
 |  332   // Clear the incoming parameters in the optimized frame to avoid | 
 |  333   // confusing the garbage collector. | 
 |  334   unsigned output_offset = output_frame_size - kPointerSize; | 
 |  335   int parameter_count = function_->shared()->formal_parameter_count() + 1; | 
 |  336   for (int i = 0; i < parameter_count; ++i) { | 
 |  337     output_[0]->SetFrameSlot(output_offset, 0); | 
 |  338     output_offset -= kPointerSize; | 
 |  339   } | 
 |  340  | 
 |  341   // Translate the incoming parameters. This may overwrite some of the | 
 |  342   // incoming argument slots we've just cleared. | 
 |  343   int input_offset = input_frame_size - kPointerSize; | 
 |  344   bool ok = true; | 
 |  345   int limit = input_offset - (parameter_count * kPointerSize); | 
 |  346   while (ok && input_offset > limit) { | 
 |  347     ok = DoOsrTranslateCommand(&iterator, &input_offset); | 
 |  348   } | 
 |  349  | 
 |  350   // There are no translation commands for the caller's pc and fp, the | 
 |  351   // context, and the function.  Set them up explicitly. | 
 |  352   for (int i = 0; ok && i < 4; i++) { | 
 |  353     intptr_t input_value = input_->GetFrameSlot(input_offset); | 
 |  354     if (FLAG_trace_osr) { | 
 |  355       PrintF("    [esp + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d] (fixed part)\n", | 
 |  356              output_offset, | 
 |  357              input_value, | 
 |  358              input_offset); | 
 |  359     } | 
 |  360     output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset)); | 
 |  361     input_offset -= kPointerSize; | 
 |  362     output_offset -= kPointerSize; | 
 |  363   } | 
 |  364  | 
 |  365   // Translate the rest of the frame. | 
 |  366   while (ok && input_offset >= 0) { | 
 |  367     ok = DoOsrTranslateCommand(&iterator, &input_offset); | 
 |  368   } | 
 |  369  | 
 |  370   // If translation of any command failed, continue using the input frame. | 
 |  371   if (!ok) { | 
 |  372     delete output_[0]; | 
 |  373     output_[0] = input_; | 
 |  374     output_[0]->SetPc(reinterpret_cast<intptr_t>(from_)); | 
 |  375   } else { | 
 |  376     // Setup the frame pointer and the context pointer. | 
 |  377     output_[0]->SetRegister(rbp.code(), input_->GetRegister(rbp.code())); | 
 |  378     output_[0]->SetRegister(rsi.code(), input_->GetRegister(rsi.code())); | 
 |  379  | 
 |  380     unsigned pc_offset = data->OsrPcOffset()->value(); | 
 |  381     intptr_t pc = reinterpret_cast<intptr_t>( | 
 |  382         optimized_code_->entry() + pc_offset); | 
 |  383     output_[0]->SetPc(pc); | 
 |  384   } | 
 |  385   Code* continuation = Builtins::builtin(Builtins::NotifyOSR); | 
 |  386   output_[0]->SetContinuation( | 
 |  387       reinterpret_cast<intptr_t>(continuation->entry())); | 
 |  388  | 
 |  389   if (FLAG_trace_osr) { | 
 |  390     PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", | 
 |  391            ok ? "finished" : "aborted", | 
 |  392            reinterpret_cast<intptr_t>(function)); | 
 |  393     function->PrintName(); | 
 |  394     PrintF(" => pc=0x%0" V8PRIxPTR "]\n", output_[0]->GetPc()); | 
 |  395   } | 
 |  396 } | 
 |  397  | 
 |  398  | 
|  259 void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, |  399 void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, | 
|  260                                  int frame_index) { |  400                                  int frame_index) { | 
|  261   // Read the ast node id, function, and frame height for this output frame. |  401   // Read the ast node id, function, and frame height for this output frame. | 
|  262   Translation::Opcode opcode = |  402   Translation::Opcode opcode = | 
|  263       static_cast<Translation::Opcode>(iterator->Next()); |  403       static_cast<Translation::Opcode>(iterator->Next()); | 
|  264   USE(opcode); |  404   USE(opcode); | 
|  265   ASSERT(Translation::FRAME == opcode); |  405   ASSERT(Translation::FRAME == opcode); | 
|  266   int node_id = iterator->Next(); |  406   int node_id = iterator->Next(); | 
|  267   JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |  407   JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 
|  268   unsigned height = iterator->Next(); |  408   unsigned height = iterator->Next(); | 
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  632   } |  772   } | 
|  633   __ bind(&done); |  773   __ bind(&done); | 
|  634 } |  774 } | 
|  635  |  775  | 
|  636 #undef __ |  776 #undef __ | 
|  637  |  777  | 
|  638  |  778  | 
|  639 } }  // namespace v8::internal |  779 } }  // namespace v8::internal | 
|  640  |  780  | 
|  641 #endif  // V8_TARGET_ARCH_X64 |  781 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW |