Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 983153002: [turbofan] Add an extra frame state for deoptimization before binary op. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Tweak Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/change-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/change-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698