| OLD | NEW |
| (Empty) |
| 1 --- src/graph-codegen.cc (revision 757) | |
| 2 +++ src/graph-codegen.cc (working copy) | |
| 3 @@ -45,6 +45,7 @@ | |
| 4 bailout_literals_(8), | |
| 5 arguments_stack_height_(0), | |
| 6 safepoint_pc_offsets_(32), | |
| 7 + safepoint_bailout_ids_(32), | |
| 8 safepoint_span_indexes_(32), | |
| 9 current_block_(NULL), | |
| 10 next_block_(NULL), | |
| 11 @@ -257,6 +258,7 @@ | |
| 12 } | |
| 13 } | |
| 14 | |
| 15 + | |
| 16 SpanList* SpanList::Insert(Span* span) { | |
| 17 return new SpanList(span, this); | |
| 18 } | |
| 19 @@ -994,90 +996,9 @@ | |
| 20 BAILOUT("attempted bailout when deoptimization is impossible"); | |
| 21 } | |
| 22 | |
| 23 - // Compute the output frame height. | |
| 24 - int height = environment_.ExpressionStackHeight(); | |
| 25 - | |
| 26 - // Build the translation. The size is the part above the frame pointer. | |
| 27 - int translation_size = height + LocalCount(); | |
| 28 - Translation translation(&translations_, translation_size); | |
| 29 - | |
| 30 - // Total output frame size: Expression stack + locals + fixed elements + | |
| 31 - // parameters and receiver. | |
| 32 - int output_frame_size = translation_size + 4 + ParameterCount() + 1; | |
| 33 - | |
| 34 - // The parameters are at the bottom of the frame. They have negative | |
| 35 - // span indices that increase (go toward zero) as the parameter index | |
| 36 - // goes up. They have positive destination indices that decrease as the | |
| 37 - // parameter index goes up. | |
| 38 - // | |
| 39 - // Output frame index of the slot above the last parameter. First '1' is | |
| 40 - // receiver, second '1' is to convert to a zero-based index. | |
| 41 - int parameter_base = output_frame_size - (ParameterCount() + 1) - 1; | |
| 42 - EnvironmentIterator parameters(&environment_, | |
| 43 - EnvironmentIterator::PARAMETERS); | |
| 44 - while (parameters.HasNext()) { | |
| 45 - Span* span = parameters.Next()->span(); | |
| 46 - ASSERT(span->HasFixedSpillSlot()); | |
| 47 - int dest_index = parameter_base - span->index(); | |
| 48 - if (span->IsAllocated()) { | |
| 49 - translation.MoveStackReg(dest_index, span->reg()); | |
| 50 - } else if (span->IsSpilled()) { | |
| 51 - // Nothing to do. Parameter already in its fixed slot. | |
| 52 - } else { | |
| 53 - UNREACHABLE(); | |
| 54 - } | |
| 55 - } | |
| 56 - | |
| 57 - // Setup the locals. Locals have positive span indices that increase as | |
| 58 - // the local index goes up. They have positive output frame indices that | |
| 59 - // decrease as the local index goes up. | |
| 60 - int output_index = translation_size - 1; // For local 0. | |
| 61 - EnvironmentIterator locals(&environment_, EnvironmentIterator::LOCALS); | |
| 62 - while (locals.HasNext()) { | |
| 63 - Span* span = locals.Next()->span(); | |
| 64 - if (span->IsAllocated()) { | |
| 65 - translation.MoveStackReg(output_index, span->reg()); | |
| 66 - } else if (span->IsSpilled()) { | |
| 67 - // TODO(kmillikin): spilled spans should be already in place in the | |
| 68 - // output frame. Eliminate this move. | |
| 69 - translation.MoveStackStack(output_index, span->index()); | |
| 70 - } else { | |
| 71 - UNREACHABLE(); | |
| 72 - } | |
| 73 - --output_index; | |
| 74 - } | |
| 75 - | |
| 76 - // Setup the rest of the expression stack. | |
| 77 - for (int i = 0; i < height; i++) { | |
| 78 - Expression* expr = environment_.ExpressionStackAt(i); | |
| 79 - Span* span = expr->span(); | |
| 80 - if (span->IsAllocated()) { | |
| 81 - translation.MoveStackReg(i, span->reg()); | |
| 82 - } else if (span->IsSpilled()) { | |
| 83 - translation.MoveStackStack(i, span->index()); | |
| 84 - } else if (span->IsArgument()) { | |
| 85 - int index = arguments_stack_height_ - (span->ArgumentIndex() + 1); | |
| 86 - translation.MoveStackArgument(i, index); | |
| 87 - } else if (expr->AsLiteral() != NULL) { | |
| 88 - int index = DefineBailoutLiteral(expr->AsLiteral()->handle()); | |
| 89 - translation.MoveStackLiteral(i, index); | |
| 90 - } else { | |
| 91 - UNREACHABLE(); | |
| 92 - } | |
| 93 - } | |
| 94 - | |
| 95 - // Emit the bailout information. | |
| 96 - int id = bailouts_.length(); | |
| 97 - Bailout bailout = { | |
| 98 - node->id(), | |
| 99 - translation.index(), | |
| 100 - arguments_stack_height_, | |
| 101 - }; | |
| 102 - bailouts_.Add(bailout); | |
| 103 + unsigned id = RecordBailout(node); | |
| 104 Address entry = Deoptimizer::GetDeoptimizationEntry(id); | |
| 105 - if (entry == NULL) { | |
| 106 - BAILOUT("bailout was not prepared"); | |
| 107 - } | |
| 108 + if (entry == NULL) BAILOUT("too many bailouts"); | |
| 109 __ j(cc, entry, RelocInfo::RUNTIME_ENTRY, not_taken); | |
| 110 } | |
| 111 | |
| 112 @@ -1920,9 +1841,102 @@ | |
| 113 } | |
| 114 safepoint_pc_offsets_.Add(masm_->pc_offset()); | |
| 115 safepoint_span_indexes_.Add(indexes); | |
| 116 + | |
| 117 + // Record a bailout at every safe point. | |
| 118 + unsigned id = RecordBailout(current_instruction()); | |
| 119 + safepoint_bailout_ids_.Add(id); | |
| 120 + if (Deoptimizer::GetDeoptimizationEntry(id) == NULL) { | |
| 121 + BAILOUT("too many bailouts"); | |
| 122 + } | |
| 123 } | |
| 124 | |
| 125 | |
| 126 +unsigned GraphCodeGenerator::RecordBailout(AstNode* node) { | |
| 127 + // Compute the output frame height. | |
| 128 + int height = environment_.ExpressionStackHeight(); | |
| 129 + | |
| 130 + // Build the translation. The size is the part above the frame pointer. | |
| 131 + int translation_size = height + LocalCount(); | |
| 132 + Translation translation(&translations_, translation_size); | |
| 133 + | |
| 134 + // Total output frame size: Expression stack + locals + fixed elements + | |
| 135 + // parameters and receiver. | |
| 136 + int output_frame_size = translation_size + 4 + ParameterCount() + 1; | |
| 137 + | |
| 138 + // The parameters are at the bottom of the frame. They have negative | |
| 139 + // span indices that increase (go toward zero) as the parameter index | |
| 140 + // goes up. They have positive destination indices that decrease as the | |
| 141 + // parameter index goes up. | |
| 142 + // | |
| 143 + // Output frame index of the slot above the last parameter. First '1' is | |
| 144 + // receiver, second '1' is to convert to a zero-based index. | |
| 145 + int parameter_base = output_frame_size - (ParameterCount() + 1) - 1; | |
| 146 + EnvironmentIterator parameters(&environment_, | |
| 147 + EnvironmentIterator::PARAMETERS); | |
| 148 + while (parameters.HasNext()) { | |
| 149 + Span* span = parameters.Next()->span(); | |
| 150 + ASSERT(span->HasFixedSpillSlot()); | |
| 151 + int dest_index = parameter_base - span->index(); | |
| 152 + if (span->IsAllocated()) { | |
| 153 + translation.MoveStackReg(dest_index, span->reg()); | |
| 154 + } else if (span->IsSpilled()) { | |
| 155 + // Nothing to do. Parameter already in its fixed slot. | |
| 156 + } else { | |
| 157 + UNREACHABLE(); | |
| 158 + } | |
| 159 + } | |
| 160 + | |
| 161 + // Setup the locals. Locals have positive span indices that increase as | |
| 162 + // the local index goes up. They have positive output frame indices that | |
| 163 + // decrease as the local index goes up. | |
| 164 + int output_index = translation_size - 1; // For local 0. | |
| 165 + EnvironmentIterator locals(&environment_, EnvironmentIterator::LOCALS); | |
| 166 + while (locals.HasNext()) { | |
| 167 + Span* span = locals.Next()->span(); | |
| 168 + if (span->IsAllocated()) { | |
| 169 + translation.MoveStackReg(output_index, span->reg()); | |
| 170 + } else if (span->IsSpilled()) { | |
| 171 + // TODO(kmillikin): spilled spans should be already in place in the | |
| 172 + // output frame. Eliminate this move. | |
| 173 + translation.MoveStackStack(output_index, span->index()); | |
| 174 + } else { | |
| 175 + UNREACHABLE(); | |
| 176 + } | |
| 177 + --output_index; | |
| 178 + } | |
| 179 + | |
| 180 + // Setup the rest of the expression stack. | |
| 181 + for (int i = 0; i < height; i++) { | |
| 182 + Expression* expr = environment_.ExpressionStackAt(i); | |
| 183 + Span* span = expr->span(); | |
| 184 + if (span->IsAllocated()) { | |
| 185 + translation.MoveStackReg(i, span->reg()); | |
| 186 + } else if (span->IsSpilled()) { | |
| 187 + translation.MoveStackStack(i, span->index()); | |
| 188 + } else if (span->IsArgument()) { | |
| 189 + int index = arguments_stack_height_ - (span->ArgumentIndex() + 1); | |
| 190 + translation.MoveStackArgument(i, index); | |
| 191 + } else if (expr->AsLiteral() != NULL) { | |
| 192 + int index = DefineBailoutLiteral(expr->AsLiteral()->handle()); | |
| 193 + translation.MoveStackLiteral(i, index); | |
| 194 + } else { | |
| 195 + UNREACHABLE(); | |
| 196 + } | |
| 197 + } | |
| 198 + | |
| 199 + // Emit the bailout information. | |
| 200 + unsigned id = bailouts_.length(); | |
| 201 + Bailout bailout = { | |
| 202 + node->id(), | |
| 203 + translation.index(), | |
| 204 + arguments_stack_height_, | |
| 205 + }; | |
| 206 + bailouts_.Add(bailout); | |
| 207 + return id; | |
| 208 + | |
| 209 +} | |
| 210 + | |
| 211 + | |
| 212 unsigned GraphCodeGenerator::EmitSafepointTable(unsigned prologue_size) { | |
| 213 // Make sure the safepoint table is properly aligned. Pad with nops. | |
| 214 static const unsigned kTableAlignment = kIntSize; | |
| OLD | NEW |