OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 Node* property_missing = | 1168 Node* property_missing = |
1169 NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant()); | 1169 NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant()); |
1170 { | 1170 { |
1171 IfBuilder is_property_missing(this); | 1171 IfBuilder is_property_missing(this); |
1172 is_property_missing.If(property_missing); | 1172 is_property_missing.If(property_missing); |
1173 is_property_missing.Then(); | 1173 is_property_missing.Then(); |
1174 // Inc counter and continue. | 1174 // Inc counter and continue. |
1175 Node* index_inc = | 1175 Node* index_inc = |
1176 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | 1176 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
1177 // TODO(jarin): provide real bailout id. | 1177 // TODO(jarin): provide real bailout id. |
1178 PrepareFrameState(index_inc, BailoutId::None()); | 1178 PrepareFrameStateAfterAndBefore(index_inc, BailoutId::None(), |
| 1179 OutputFrameStateCombine::Ignore(), |
| 1180 jsgraph()->EmptyFrameState()); |
1179 environment()->Poke(0, index_inc); | 1181 environment()->Poke(0, index_inc); |
1180 for_loop.Continue(); | 1182 for_loop.Continue(); |
1181 is_property_missing.Else(); | 1183 is_property_missing.Else(); |
1182 is_property_missing.End(); | 1184 is_property_missing.End(); |
1183 } | 1185 } |
1184 // Replace 'value' in environment. | 1186 // Replace 'value' in environment. |
1185 environment()->Push(res); | 1187 environment()->Push(res); |
1186 test_should_filter.Else(); | 1188 test_should_filter.Else(); |
1187 test_should_filter.End(); | 1189 test_should_filter.End(); |
1188 } | 1190 } |
1189 value = environment()->Pop(); | 1191 value = environment()->Pop(); |
1190 // Bind value and do loop body. | 1192 // Bind value and do loop body. |
1191 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); | 1193 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); |
1192 VisitIterationBody(stmt, &for_loop); | 1194 VisitIterationBody(stmt, &for_loop); |
1193 for_loop.EndBody(); | 1195 for_loop.EndBody(); |
1194 // Inc counter and continue. | 1196 // Inc counter and continue. |
1195 Node* index_inc = | 1197 Node* index_inc = |
1196 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | 1198 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
1197 // TODO(jarin): provide real bailout id. | 1199 // TODO(jarin): provide real bailout id. |
1198 PrepareFrameState(index_inc, BailoutId::None()); | 1200 PrepareFrameStateAfterAndBefore(index_inc, BailoutId::None(), |
| 1201 OutputFrameStateCombine::Ignore(), |
| 1202 jsgraph()->EmptyFrameState()); |
1199 environment()->Poke(0, index_inc); | 1203 environment()->Poke(0, index_inc); |
1200 for_loop.EndLoop(); | 1204 for_loop.EndLoop(); |
1201 environment()->Drop(5); | 1205 environment()->Drop(5); |
1202 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1206 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1203 } | 1207 } |
1204 | 1208 |
1205 | 1209 |
1206 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { | 1210 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
1207 LoopBuilder for_loop(this); | 1211 LoopBuilder for_loop(this); |
1208 VisitForEffect(stmt->assign_iterator()); | 1212 VisitForEffect(stmt->assign_iterator()); |
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1809 VectorSlotPair pair = | 1813 VectorSlotPair pair = |
1810 CreateVectorSlotPair(property->PropertyFeedbackSlot()); | 1814 CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
1811 old_value = NewNode(javascript()->LoadProperty(pair), object, key); | 1815 old_value = NewNode(javascript()->LoadProperty(pair), object, key); |
1812 PrepareFrameState(old_value, property->LoadId(), | 1816 PrepareFrameState(old_value, property->LoadId(), |
1813 OutputFrameStateCombine::Push()); | 1817 OutputFrameStateCombine::Push()); |
1814 break; | 1818 break; |
1815 } | 1819 } |
1816 } | 1820 } |
1817 environment()->Push(old_value); | 1821 environment()->Push(old_value); |
1818 VisitForValue(expr->value()); | 1822 VisitForValue(expr->value()); |
| 1823 Node* frame_state_before = environment()->Checkpoint(expr->value()->id()); |
1819 Node* right = environment()->Pop(); | 1824 Node* right = environment()->Pop(); |
1820 Node* left = environment()->Pop(); | 1825 Node* left = environment()->Pop(); |
1821 Node* value = BuildBinaryOp(left, right, expr->binary_op()); | 1826 Node* value = BuildBinaryOp(left, right, expr->binary_op()); |
1822 PrepareFrameState(value, expr->binary_operation()->id(), | 1827 PrepareFrameStateAfterAndBefore(value, expr->binary_operation()->id(), |
1823 OutputFrameStateCombine::Push()); | 1828 OutputFrameStateCombine::Push(), |
| 1829 frame_state_before); |
1824 environment()->Push(value); | 1830 environment()->Push(value); |
1825 } else { | 1831 } else { |
1826 VisitForValue(expr->value()); | 1832 VisitForValue(expr->value()); |
1827 } | 1833 } |
1828 | 1834 |
1829 // Store the value. | 1835 // Store the value. |
1830 Node* value = environment()->Pop(); | 1836 Node* value = environment()->Pop(); |
1831 switch (assign_type) { | 1837 switch (assign_type) { |
1832 case VARIABLE: { | 1838 case VARIABLE: { |
1833 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1839 Variable* variable = expr->target()->AsVariableProxy()->var(); |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2161 old_value = NewNode(javascript()->ToNumber(), old_value); | 2167 old_value = NewNode(javascript()->ToNumber(), old_value); |
2162 PrepareFrameState(old_value, expr->ToNumberId(), | 2168 PrepareFrameState(old_value, expr->ToNumberId(), |
2163 OutputFrameStateCombine::Push()); | 2169 OutputFrameStateCombine::Push()); |
2164 | 2170 |
2165 // Save result for postfix expressions at correct stack depth. | 2171 // Save result for postfix expressions at correct stack depth. |
2166 if (is_postfix) environment()->Poke(stack_depth, old_value); | 2172 if (is_postfix) environment()->Poke(stack_depth, old_value); |
2167 | 2173 |
2168 // Create node to perform +1/-1 operation. | 2174 // Create node to perform +1/-1 operation. |
2169 Node* value = | 2175 Node* value = |
2170 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); | 2176 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); |
2171 // TODO(jarin) Insert proper bailout id here (will need to change | 2177 // This should never deoptimize because we have converted to number |
2172 // full code generator). | 2178 // before. |
2173 PrepareFrameState(value, BailoutId::None()); | 2179 PrepareFrameStateAfterAndBefore(value, BailoutId::None(), |
| 2180 OutputFrameStateCombine::Ignore(), |
| 2181 jsgraph()->EmptyFrameState()); |
2174 | 2182 |
2175 // Store the value. | 2183 // Store the value. |
2176 switch (assign_type) { | 2184 switch (assign_type) { |
2177 case VARIABLE: { | 2185 case VARIABLE: { |
2178 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2186 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
2179 environment()->Push(value); | 2187 environment()->Push(value); |
2180 BuildVariableAssignment(variable, value, expr->op(), | 2188 BuildVariableAssignment(variable, value, expr->op(), |
2181 expr->AssignmentId()); | 2189 expr->AssignmentId()); |
2182 environment()->Pop(); | 2190 environment()->Pop(); |
2183 break; | 2191 break; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2215 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 2223 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
2216 switch (expr->op()) { | 2224 switch (expr->op()) { |
2217 case Token::COMMA: | 2225 case Token::COMMA: |
2218 return VisitComma(expr); | 2226 return VisitComma(expr); |
2219 case Token::OR: | 2227 case Token::OR: |
2220 case Token::AND: | 2228 case Token::AND: |
2221 return VisitLogicalExpression(expr); | 2229 return VisitLogicalExpression(expr); |
2222 default: { | 2230 default: { |
2223 VisitForValue(expr->left()); | 2231 VisitForValue(expr->left()); |
2224 VisitForValue(expr->right()); | 2232 VisitForValue(expr->right()); |
| 2233 Node* frame_state_before = environment()->Checkpoint(expr->right()->id()); |
2225 Node* right = environment()->Pop(); | 2234 Node* right = environment()->Pop(); |
2226 Node* left = environment()->Pop(); | 2235 Node* left = environment()->Pop(); |
2227 Node* value = BuildBinaryOp(left, right, expr->op()); | 2236 Node* value = BuildBinaryOp(left, right, expr->op()); |
2228 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 2237 PrepareFrameStateAfterAndBefore(value, expr->id(), |
| 2238 ast_context()->GetStateCombine(), |
| 2239 frame_state_before); |
2229 ast_context()->ProduceValue(value); | 2240 ast_context()->ProduceValue(value); |
2230 } | 2241 } |
2231 } | 2242 } |
2232 } | 2243 } |
2233 | 2244 |
2234 | 2245 |
2235 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 2246 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
2236 const Operator* op; | 2247 const Operator* op; |
2237 switch (expr->op()) { | 2248 switch (expr->op()) { |
2238 case Token::EQ: | 2249 case Token::EQ: |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2953 info()->set_osr_expr_stack_height(std::max( | 2964 info()->set_osr_expr_stack_height(std::max( |
2954 environment()->stack_height(), info()->osr_expr_stack_height())); | 2965 environment()->stack_height(), info()->osr_expr_stack_height())); |
2955 return true; | 2966 return true; |
2956 } | 2967 } |
2957 return false; | 2968 return false; |
2958 } | 2969 } |
2959 | 2970 |
2960 | 2971 |
2961 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, | 2972 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, |
2962 OutputFrameStateCombine combine) { | 2973 OutputFrameStateCombine combine) { |
2963 if (OperatorProperties::HasFrameStateInput(node->op())) { | 2974 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { |
2964 DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() == | 2975 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
2965 IrOpcode::kDead); | 2976 |
| 2977 DCHECK_EQ(IrOpcode::kDead, |
| 2978 NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
2966 NodeProperties::ReplaceFrameStateInput( | 2979 NodeProperties::ReplaceFrameStateInput( |
2967 node, environment()->Checkpoint(ast_id, combine)); | 2980 node, 0, environment()->Checkpoint(ast_id, combine)); |
2968 } | 2981 } |
2969 } | 2982 } |
2970 | 2983 |
| 2984 |
| 2985 void AstGraphBuilder::PrepareFrameStateAfterAndBefore( |
| 2986 Node* node, BailoutId ast_id, OutputFrameStateCombine combine, |
| 2987 Node* frame_state_before) { |
| 2988 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { |
| 2989 DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op())); |
| 2990 |
| 2991 DCHECK_EQ(IrOpcode::kDead, |
| 2992 NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
| 2993 NodeProperties::ReplaceFrameStateInput( |
| 2994 node, 0, environment()->Checkpoint(ast_id, combine)); |
| 2995 |
| 2996 DCHECK_EQ(IrOpcode::kDead, |
| 2997 NodeProperties::GetFrameStateInput(node, 1)->opcode()); |
| 2998 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before); |
| 2999 } |
| 3000 } |
| 3001 |
2971 | 3002 |
2972 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 3003 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
2973 IterationStatement* stmt) { | 3004 IterationStatement* stmt) { |
2974 if (loop_assignment_analysis_ == NULL) return NULL; | 3005 if (loop_assignment_analysis_ == NULL) return NULL; |
2975 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 3006 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
2976 } | 3007 } |
2977 | 3008 |
2978 | 3009 |
2979 Node** AstGraphBuilder::EnsureInputBufferSize(int size) { | 3010 Node** AstGraphBuilder::EnsureInputBufferSize(int size) { |
2980 if (size > input_buffer_size_) { | 3011 if (size > input_buffer_size_) { |
2981 size = size + kInputBufferSizeIncrement + input_buffer_size_; | 3012 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
2982 input_buffer_ = local_zone()->NewArray<Node*>(size); | 3013 input_buffer_ = local_zone()->NewArray<Node*>(size); |
2983 input_buffer_size_ = size; | 3014 input_buffer_size_ = size; |
2984 } | 3015 } |
2985 return input_buffer_; | 3016 return input_buffer_; |
2986 } | 3017 } |
2987 | 3018 |
2988 | 3019 |
2989 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, | 3020 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
2990 Node** value_inputs, bool incomplete) { | 3021 Node** value_inputs, bool incomplete) { |
2991 DCHECK(op->ValueInputCount() == value_input_count); | 3022 DCHECK(op->ValueInputCount() == value_input_count); |
2992 | 3023 |
2993 bool has_context = OperatorProperties::HasContextInput(op); | 3024 bool has_context = OperatorProperties::HasContextInput(op); |
2994 bool has_framestate = OperatorProperties::HasFrameStateInput(op); | 3025 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op); |
2995 bool has_control = op->ControlInputCount() == 1; | 3026 bool has_control = op->ControlInputCount() == 1; |
2996 bool has_effect = op->EffectInputCount() == 1; | 3027 bool has_effect = op->EffectInputCount() == 1; |
2997 | 3028 |
2998 DCHECK(op->ControlInputCount() < 2); | 3029 DCHECK(op->ControlInputCount() < 2); |
2999 DCHECK(op->EffectInputCount() < 2); | 3030 DCHECK(op->EffectInputCount() < 2); |
3000 | 3031 |
3001 Node* result = NULL; | 3032 Node* result = NULL; |
3002 if (!has_context && !has_framestate && !has_control && !has_effect) { | 3033 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { |
3003 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 3034 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
3004 } else { | 3035 } else { |
3005 bool inside_try_scope = try_nesting_level_ > 0; | 3036 bool inside_try_scope = try_nesting_level_ > 0; |
3006 int input_count_with_deps = value_input_count; | 3037 int input_count_with_deps = value_input_count; |
3007 if (has_context) ++input_count_with_deps; | 3038 if (has_context) ++input_count_with_deps; |
3008 if (has_framestate) ++input_count_with_deps; | 3039 input_count_with_deps += frame_state_count; |
3009 if (has_control) ++input_count_with_deps; | 3040 if (has_control) ++input_count_with_deps; |
3010 if (has_effect) ++input_count_with_deps; | 3041 if (has_effect) ++input_count_with_deps; |
3011 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 3042 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
3012 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | 3043 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
3013 Node** current_input = buffer + value_input_count; | 3044 Node** current_input = buffer + value_input_count; |
3014 if (has_context) { | 3045 if (has_context) { |
3015 *current_input++ = current_context(); | 3046 *current_input++ = current_context(); |
3016 } | 3047 } |
3017 if (has_framestate) { | 3048 for (int i = 0; i < frame_state_count; i++) { |
3018 // The frame state will be inserted later. Here we misuse | 3049 // The frame state will be inserted later. Here we misuse |
3019 // the {DeadControl} node as a sentinel to be later overwritten | 3050 // the {DeadControl} node as a sentinel to be later overwritten |
3020 // with the real frame state. | 3051 // with the real frame state. |
3021 *current_input++ = jsgraph()->DeadControl(); | 3052 *current_input++ = jsgraph()->DeadControl(); |
3022 } | 3053 } |
3023 if (has_effect) { | 3054 if (has_effect) { |
3024 *current_input++ = environment_->GetEffectDependency(); | 3055 *current_input++ = environment_->GetEffectDependency(); |
3025 } | 3056 } |
3026 if (has_control) { | 3057 if (has_control) { |
3027 *current_input++ = environment_->GetControlDependency(); | 3058 *current_input++ = environment_->GetControlDependency(); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3250 // Phi does not exist yet, introduce one. | 3281 // Phi does not exist yet, introduce one. |
3251 value = NewPhi(inputs, value, control); | 3282 value = NewPhi(inputs, value, control); |
3252 value->ReplaceInput(inputs - 1, other); | 3283 value->ReplaceInput(inputs - 1, other); |
3253 } | 3284 } |
3254 return value; | 3285 return value; |
3255 } | 3286 } |
3256 | 3287 |
3257 } // namespace compiler | 3288 } // namespace compiler |
3258 } // namespace internal | 3289 } // namespace internal |
3259 } // namespace v8 | 3290 } // namespace v8 |
OLD | NEW |