| 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 |