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

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

Issue 2521233002: [fullcodegen] Remove exception handling support. (Closed)
Patch Set: Rebased. Created 4 years 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/control-builders.h » ('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/ast/compile-time-value.h" 7 #include "src/ast/compile-time-value.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/compilation-info.h" 9 #include "src/compilation-info.h"
10 #include "src/compiler.h" 10 #include "src/compiler.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 } 158 }
159 159
160 // Either 'break' or 'continue' to the target statement. 160 // Either 'break' or 'continue' to the target statement.
161 void BreakTo(BreakableStatement* target); 161 void BreakTo(BreakableStatement* target);
162 void ContinueTo(BreakableStatement* target); 162 void ContinueTo(BreakableStatement* target);
163 163
164 // Either 'return' or 'throw' the given value. 164 // Either 'return' or 'throw' the given value.
165 void ReturnValue(Node* return_value); 165 void ReturnValue(Node* return_value);
166 void ThrowValue(Node* exception_value); 166 void ThrowValue(Node* exception_value);
167 167
168 class DeferredCommands;
169
170 protected: 168 protected:
171 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW }; 169 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
172 170
173 // Performs one of the above commands on this stack of control scopes. This 171 // Performs one of the above commands on this stack of control scopes. This
174 // walks through the stack giving each scope a chance to execute or defer the 172 // walks through the stack giving each scope a chance to execute or defer the
175 // given command by overriding the {Execute} method appropriately. Note that 173 // given command by overriding the {Execute} method appropriately. Note that
176 // this also drops extra operands from the environment for each skipped scope. 174 // this also drops extra operands from the environment for each skipped scope.
177 void PerformCommand(Command cmd, Statement* target, Node* value); 175 void PerformCommand(Command cmd, Statement* target, Node* value);
178 176
179 // Interface to execute a given command in this scope. Returning {true} here 177 // Interface to execute a given command in this scope. Returning {true} here
(...skipping 19 matching lines...) Expand all
199 int context_length() const { return context_length_; } 197 int context_length() const { return context_length_; }
200 int stack_height() const { return stack_height_; } 198 int stack_height() const { return stack_height_; }
201 199
202 private: 200 private:
203 AstGraphBuilder* builder_; 201 AstGraphBuilder* builder_;
204 ControlScope* outer_; 202 ControlScope* outer_;
205 int context_length_; 203 int context_length_;
206 int stack_height_; 204 int stack_height_;
207 }; 205 };
208 206
209 // Helper class for a try-finally control scope. It can record intercepted
210 // control-flow commands that cause entry into a finally-block, and re-apply
211 // them after again leaving that block. Special tokens are used to identify
212 // paths going through the finally-block to dispatch after leaving the block.
213 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
214 public:
215 explicit DeferredCommands(AstGraphBuilder* owner)
216 : owner_(owner),
217 deferred_(owner->local_zone()),
218 return_token_(nullptr),
219 throw_token_(nullptr) {}
220
221 // One recorded control-flow command.
222 struct Entry {
223 Command command; // The command type being applied on this path.
224 Statement* statement; // The target statement for the command or {nullptr}.
225 Node* token; // A token identifying this particular path.
226 };
227
228 // Records a control-flow command while entering the finally-block. This also
229 // generates a new dispatch token that identifies one particular path.
230 Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
231 Node* token = nullptr;
232 switch (cmd) {
233 case CMD_BREAK:
234 case CMD_CONTINUE:
235 token = NewPathToken(dispenser_.GetBreakContinueToken());
236 break;
237 case CMD_THROW:
238 if (throw_token_) return throw_token_;
239 token = NewPathToken(TokenDispenserForFinally::kThrowToken);
240 throw_token_ = token;
241 break;
242 case CMD_RETURN:
243 if (return_token_) return return_token_;
244 token = NewPathToken(TokenDispenserForFinally::kReturnToken);
245 return_token_ = token;
246 break;
247 }
248 DCHECK_NOT_NULL(token);
249 deferred_.push_back({cmd, stmt, token});
250 return token;
251 }
252
253 // Returns the dispatch token to be used to identify the implicit fall-through
254 // path at the end of a try-block into the corresponding finally-block.
255 Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
256
257 // Applies all recorded control-flow commands after the finally-block again.
258 // This generates a dynamic dispatch on the token from the entry point.
259 void ApplyDeferredCommands(Node* token, Node* value) {
260 SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
261 dispatch.BeginSwitch();
262 for (size_t i = 0; i < deferred_.size(); ++i) {
263 Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
264 dispatch.BeginLabel(static_cast<int>(i), condition);
265 dispatch.EndLabel();
266 }
267 for (size_t i = 0; i < deferred_.size(); ++i) {
268 dispatch.BeginCase(static_cast<int>(i));
269 owner_->execution_control()->PerformCommand(
270 deferred_[i].command, deferred_[i].statement, value);
271 dispatch.EndCase();
272 }
273 dispatch.EndSwitch();
274 }
275
276 protected:
277 Node* NewPathToken(int token_id) {
278 return owner_->jsgraph()->Constant(token_id);
279 }
280 Node* NewPathTokenForImplicitFallThrough() {
281 return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
282 }
283 Node* NewPathDispatchCondition(Node* t1, Node* t2) {
284 return owner_->NewNode(
285 owner_->javascript()->StrictEqual(CompareOperationHint::kAny), t1, t2);
286 }
287
288 private:
289 TokenDispenserForFinally dispenser_;
290 AstGraphBuilder* owner_;
291 ZoneVector<Entry> deferred_;
292 Node* return_token_;
293 Node* throw_token_;
294 };
295
296 207
297 // Control scope implementation for a BreakableStatement. 208 // Control scope implementation for a BreakableStatement.
298 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { 209 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
299 public: 210 public:
300 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, 211 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
301 ControlBuilder* control) 212 ControlBuilder* control)
302 : ControlScope(owner), target_(target), control_(control) {} 213 : ControlScope(owner), target_(target), control_(control) {}
303 214
304 protected: 215 protected:
305 bool Execute(Command cmd, Statement* target, Node** value) override { 216 bool Execute(Command cmd, Statement* target, Node** value) override {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 } 259 }
349 return false; 260 return false;
350 } 261 }
351 262
352 private: 263 private:
353 BreakableStatement* target_; 264 BreakableStatement* target_;
354 LoopBuilder* control_; 265 LoopBuilder* control_;
355 }; 266 };
356 267
357 268
358 // Control scope implementation for a TryCatchStatement.
359 class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
360 public:
361 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchStatement* stmt,
362 TryCatchBuilder* control)
363 : ControlScope(owner), control_(control) {
364 builder()->try_nesting_level_++; // Increment nesting.
365 }
366 ~ControlScopeForCatch() {
367 builder()->try_nesting_level_--; // Decrement nesting.
368 }
369
370 protected:
371 bool Execute(Command cmd, Statement* target, Node** value) override {
372 switch (cmd) {
373 case CMD_THROW:
374 control_->Throw(*value);
375 return true;
376 case CMD_BREAK:
377 case CMD_CONTINUE:
378 case CMD_RETURN:
379 break;
380 }
381 return false;
382 }
383
384 private:
385 TryCatchBuilder* control_;
386 };
387
388
389 // Control scope implementation for a TryFinallyStatement.
390 class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
391 public:
392 ControlScopeForFinally(AstGraphBuilder* owner, TryFinallyStatement* stmt,
393 DeferredCommands* commands, TryFinallyBuilder* control)
394 : ControlScope(owner), commands_(commands), control_(control) {
395 builder()->try_nesting_level_++; // Increment nesting.
396 }
397 ~ControlScopeForFinally() {
398 builder()->try_nesting_level_--; // Decrement nesting.
399 }
400
401 protected:
402 bool Execute(Command cmd, Statement* target, Node** value) override {
403 Node* token = commands_->RecordCommand(cmd, target, *value);
404 control_->LeaveTry(token, *value);
405 return true;
406 }
407
408 private:
409 DeferredCommands* commands_;
410 TryFinallyBuilder* control_;
411 };
412
413 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, 269 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
414 JSGraph* jsgraph, float invocation_frequency, 270 JSGraph* jsgraph, float invocation_frequency,
415 LoopAssignmentAnalysis* loop) 271 LoopAssignmentAnalysis* loop)
416 : isolate_(info->isolate()), 272 : isolate_(info->isolate()),
417 local_zone_(local_zone), 273 local_zone_(local_zone),
418 info_(info), 274 info_(info),
419 jsgraph_(jsgraph), 275 jsgraph_(jsgraph),
420 invocation_frequency_(invocation_frequency), 276 invocation_frequency_(invocation_frequency),
421 environment_(nullptr), 277 environment_(nullptr),
422 ast_context_(nullptr), 278 ast_context_(nullptr),
423 globals_(0, local_zone), 279 globals_(0, local_zone),
424 execution_control_(nullptr), 280 execution_control_(nullptr),
425 execution_context_(nullptr), 281 execution_context_(nullptr),
426 try_nesting_level_(0),
427 input_buffer_size_(0), 282 input_buffer_size_(0),
428 input_buffer_(nullptr), 283 input_buffer_(nullptr),
429 exit_controls_(local_zone), 284 exit_controls_(local_zone),
430 loop_assignment_analysis_(loop), 285 loop_assignment_analysis_(loop),
431 state_values_cache_(jsgraph), 286 state_values_cache_(jsgraph),
432 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()), 287 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
433 false, local_zone), 288 false, local_zone),
434 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( 289 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
435 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1, 290 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
436 info->scope()->num_stack_slots(), info->shared_info())) { 291 info->scope()->num_stack_slots(), info->shared_info())) {
(...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 Node* condition = environment()->Pop(); 1306 Node* condition = environment()->Pop();
1452 for_loop.BreakWhen(condition); 1307 for_loop.BreakWhen(condition);
1453 VisitForEffect(stmt->assign_each()); 1308 VisitForEffect(stmt->assign_each());
1454 VisitIterationBody(stmt, &for_loop, stmt->StackCheckId()); 1309 VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
1455 for_loop.EndBody(); 1310 for_loop.EndBody();
1456 for_loop.EndLoop(); 1311 for_loop.EndLoop();
1457 } 1312 }
1458 1313
1459 1314
1460 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 1315 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1461 TryCatchBuilder try_control(this); 1316 // Exception handling is supported only by going through Ignition first.
1462 1317 UNREACHABLE();
1463 // Evaluate the try-block inside a control scope. This simulates a handler
1464 // that is intercepting 'throw' control commands.
1465 try_control.BeginTry();
1466 {
1467 ControlScopeForCatch scope(this, stmt, &try_control);
1468 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1469 environment()->Push(current_context());
1470 Visit(stmt->try_block());
1471 environment()->Pop();
1472 }
1473 try_control.EndTry();
1474
1475 // If requested, clear message object as we enter the catch block.
1476 if (stmt->clear_pending_message()) {
1477 Node* the_hole = jsgraph()->TheHoleConstant();
1478 NewNode(javascript()->StoreMessage(), the_hole);
1479 }
1480
1481 // Create a catch scope that binds the exception.
1482 Node* exception = try_control.GetExceptionNode();
1483 Handle<String> name = stmt->variable()->name();
1484 Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
1485 const Operator* op = javascript()->CreateCatchContext(name, scope_info);
1486 Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1487
1488 // Evaluate the catch-block.
1489 VisitInScope(stmt->catch_block(), stmt->scope(), context);
1490 try_control.EndCatch();
1491 } 1318 }
1492 1319
1493 1320
1494 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1321 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1495 TryFinallyBuilder try_control(this); 1322 // Exception handling is supported only by going through Ignition first.
1496 1323 UNREACHABLE();
1497 // We keep a record of all paths that enter the finally-block to be able to
1498 // dispatch to the correct continuation point after the statements in the
1499 // finally-block have been evaluated.
1500 //
1501 // The try-finally construct can enter the finally-block in three ways:
1502 // 1. By exiting the try-block normally, falling through at the end.
1503 // 2. By exiting the try-block with a function-local control flow transfer
1504 // (i.e. through break/continue/return statements).
1505 // 3. By exiting the try-block with a thrown exception.
1506 Node* fallthrough_result = jsgraph()->TheHoleConstant();
1507 ControlScope::DeferredCommands* commands =
1508 new (local_zone()) ControlScope::DeferredCommands(this);
1509
1510 // Evaluate the try-block inside a control scope. This simulates a handler
1511 // that is intercepting all control commands.
1512 try_control.BeginTry();
1513 {
1514 ControlScopeForFinally scope(this, stmt, commands, &try_control);
1515 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1516 environment()->Push(current_context());
1517 Visit(stmt->try_block());
1518 environment()->Pop();
1519 }
1520 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1521
1522 // The result value semantics depend on how the block was entered:
1523 // - ReturnStatement: It represents the return value being returned.
1524 // - ThrowStatement: It represents the exception being thrown.
1525 // - BreakStatement/ContinueStatement: Filled with the hole.
1526 // - Falling through into finally-block: Filled with the hole.
1527 Node* result = try_control.GetResultValueNode();
1528 Node* token = try_control.GetDispatchTokenNode();
1529
1530 // The result value, dispatch token and message is expected on the operand
1531 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1532 Node* message = NewNode(javascript()->LoadMessage());
1533 environment()->Push(token);
1534 environment()->Push(result);
1535 environment()->Push(message);
1536
1537 // Clear message object as we enter the finally block.
1538 Node* the_hole = jsgraph()->TheHoleConstant();
1539 NewNode(javascript()->StoreMessage(), the_hole);
1540
1541 // Evaluate the finally-block.
1542 Visit(stmt->finally_block());
1543 try_control.EndFinally();
1544
1545 // The result value, dispatch token and message is restored from the operand
1546 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1547 message = environment()->Pop();
1548 result = environment()->Pop();
1549 token = environment()->Pop();
1550 NewNode(javascript()->StoreMessage(), message);
1551
1552 // Dynamic dispatch after the finally-block.
1553 commands->ApplyDeferredCommands(token, result);
1554 } 1324 }
1555 1325
1556 1326
1557 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 1327 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1558 Node* node = 1328 Node* node =
1559 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); 1329 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
1560 PrepareFrameState(node, stmt->DebugBreakId()); 1330 PrepareFrameState(node, stmt->DebugBreakId());
1561 environment()->MarkAllLocalsLive(); 1331 environment()->MarkAllLocalsLive();
1562 } 1332 }
1563 1333
(...skipping 2480 matching lines...) Expand 10 before | Expand all | Expand 10 after
4044 bool has_control = op->ControlInputCount() == 1; 3814 bool has_control = op->ControlInputCount() == 1;
4045 bool has_effect = op->EffectInputCount() == 1; 3815 bool has_effect = op->EffectInputCount() == 1;
4046 3816
4047 DCHECK(op->ControlInputCount() < 2); 3817 DCHECK(op->ControlInputCount() < 2);
4048 DCHECK(op->EffectInputCount() < 2); 3818 DCHECK(op->EffectInputCount() < 2);
4049 3819
4050 Node* result = nullptr; 3820 Node* result = nullptr;
4051 if (!has_context && !has_frame_state && !has_control && !has_effect) { 3821 if (!has_context && !has_frame_state && !has_control && !has_effect) {
4052 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); 3822 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4053 } else { 3823 } else {
4054 bool inside_try_scope = try_nesting_level_ > 0;
4055 int input_count_with_deps = value_input_count; 3824 int input_count_with_deps = value_input_count;
4056 if (has_context) ++input_count_with_deps; 3825 if (has_context) ++input_count_with_deps;
4057 if (has_frame_state) ++input_count_with_deps; 3826 if (has_frame_state) ++input_count_with_deps;
4058 if (has_control) ++input_count_with_deps; 3827 if (has_control) ++input_count_with_deps;
4059 if (has_effect) ++input_count_with_deps; 3828 if (has_effect) ++input_count_with_deps;
4060 Node** buffer = EnsureInputBufferSize(input_count_with_deps); 3829 Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4061 memcpy(buffer, value_inputs, kPointerSize * value_input_count); 3830 memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4062 Node** current_input = buffer + value_input_count; 3831 Node** current_input = buffer + value_input_count;
4063 if (has_context) { 3832 if (has_context) {
4064 *current_input++ = current_context(); 3833 *current_input++ = current_context();
(...skipping 13 matching lines...) Expand all
4078 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); 3847 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4079 if (!environment()->IsMarkedAsUnreachable()) { 3848 if (!environment()->IsMarkedAsUnreachable()) {
4080 // Update the current control dependency for control-producing nodes. 3849 // Update the current control dependency for control-producing nodes.
4081 if (NodeProperties::IsControl(result)) { 3850 if (NodeProperties::IsControl(result)) {
4082 environment_->UpdateControlDependency(result); 3851 environment_->UpdateControlDependency(result);
4083 } 3852 }
4084 // Update the current effect dependency for effect-producing nodes. 3853 // Update the current effect dependency for effect-producing nodes.
4085 if (result->op()->EffectOutputCount() > 0) { 3854 if (result->op()->EffectOutputCount() > 0) {
4086 environment_->UpdateEffectDependency(result); 3855 environment_->UpdateEffectDependency(result);
4087 } 3856 }
4088 // Add implicit exception continuation for throwing nodes.
4089 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4090 // Copy the environment for the success continuation.
4091 Environment* success_env = environment()->CopyForConditional();
4092 const Operator* op = common()->IfException();
4093 Node* effect = environment()->GetEffectDependency();
4094 Node* on_exception = graph()->NewNode(op, effect, result);
4095 environment_->UpdateControlDependency(on_exception);
4096 environment_->UpdateEffectDependency(on_exception);
4097 execution_control()->ThrowValue(on_exception);
4098 set_environment(success_env);
4099 }
4100 // Add implicit success continuation for throwing nodes. 3857 // Add implicit success continuation for throwing nodes.
4101 if (!result->op()->HasProperty(Operator::kNoThrow)) { 3858 if (!result->op()->HasProperty(Operator::kNoThrow)) {
4102 const Operator* op = common()->IfSuccess(); 3859 const Operator* op = common()->IfSuccess();
4103 Node* on_success = graph()->NewNode(op, result); 3860 Node* on_success = graph()->NewNode(op, result);
4104 environment_->UpdateControlDependency(on_success); 3861 environment_->UpdateControlDependency(on_success);
4105 } 3862 }
4106 } 3863 }
4107 } 3864 }
4108 3865
4109 return result; 3866 return result;
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
4344 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, 4101 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment,
4345 SourcePositionTable* source_positions, int inlining_id) 4102 SourcePositionTable* source_positions, int inlining_id)
4346 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, 4103 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency,
4347 loop_assignment), 4104 loop_assignment),
4348 source_positions_(source_positions), 4105 source_positions_(source_positions),
4349 start_position_(info->shared_info()->start_position(), inlining_id) {} 4106 start_position_(info->shared_info()->start_position(), inlining_id) {}
4350 4107
4351 } // namespace compiler 4108 } // namespace compiler
4352 } // namespace internal 4109 } // namespace internal
4353 } // namespace v8 4110 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698