Chromium Code Reviews| 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 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1245 try_control.EndCatch(); | 1245 try_control.EndCatch(); |
| 1246 | 1246 |
| 1247 // TODO(mstarzinger): Remove bailout once everything works. | 1247 // TODO(mstarzinger): Remove bailout once everything works. |
| 1248 if (!FLAG_turbo_exceptions) SetStackOverflow(); | 1248 if (!FLAG_turbo_exceptions) SetStackOverflow(); |
| 1249 } | 1249 } |
| 1250 | 1250 |
| 1251 | 1251 |
| 1252 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1252 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1253 TryFinallyBuilder try_control(this); | 1253 TryFinallyBuilder try_control(this); |
| 1254 | 1254 |
| 1255 ExternalReference message_object = | |
| 1256 ExternalReference::address_of_pending_message_obj(isolate()); | |
| 1257 ExternalReference message_present = | |
| 1258 ExternalReference::address_of_has_pending_message(isolate()); | |
| 1259 ExternalReference message_script = | |
| 1260 ExternalReference::address_of_pending_message_script(isolate()); | |
| 1261 | |
| 1255 // We keep a record of all paths that enter the finally-block to be able to | 1262 // We keep a record of all paths that enter the finally-block to be able to |
| 1256 // dispatch to the correct continuation point after the statements in the | 1263 // dispatch to the correct continuation point after the statements in the |
| 1257 // finally-block have been evaluated. | 1264 // finally-block have been evaluated. |
| 1258 // | 1265 // |
| 1259 // The try-finally construct can enter the finally-block in three ways: | 1266 // The try-finally construct can enter the finally-block in three ways: |
| 1260 // 1. By exiting the try-block normally, falling through at the end. | 1267 // 1. By exiting the try-block normally, falling through at the end. |
| 1261 // 2. By exiting the try-block with a function-local control flow transfer | 1268 // 2. By exiting the try-block with a function-local control flow transfer |
| 1262 // (i.e. through break/continue/return statements). | 1269 // (i.e. through break/continue/return statements). |
| 1263 // 3. By exiting the try-block with a thrown exception. | 1270 // 3. By exiting the try-block with a thrown exception. |
| 1264 Node* fallthrough_result = jsgraph()->TheHoleConstant(); | 1271 Node* fallthrough_result = jsgraph()->TheHoleConstant(); |
| 1265 ControlScope::DeferredCommands* commands = | 1272 ControlScope::DeferredCommands* commands = |
| 1266 new (zone()) ControlScope::DeferredCommands(this); | 1273 new (zone()) ControlScope::DeferredCommands(this); |
| 1267 | 1274 |
| 1268 // Evaluate the try-block inside a control scope. This simulates a handler | 1275 // Evaluate the try-block inside a control scope. This simulates a handler |
| 1269 // that is intercepting all control commands. | 1276 // that is intercepting all control commands. |
| 1270 try_control.BeginTry(); | 1277 try_control.BeginTry(); |
| 1271 { | 1278 { |
| 1272 ControlScopeForFinally scope(this, commands, &try_control); | 1279 ControlScopeForFinally scope(this, commands, &try_control); |
| 1273 Visit(stmt->try_block()); | 1280 Visit(stmt->try_block()); |
| 1274 } | 1281 } |
| 1275 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result); | 1282 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result); |
| 1276 | 1283 |
| 1277 // The result value semantics depend on how the block was entered: | 1284 // The result value semantics depend on how the block was entered: |
| 1278 // - ReturnStatement: It represents the return value being returned. | 1285 // - ReturnStatement: It represents the return value being returned. |
| 1279 // - ThrowStatement: It represents the exception being thrown. | 1286 // - ThrowStatement: It represents the exception being thrown. |
| 1280 // - BreakStatement/ContinueStatement: Filled with the hole. | 1287 // - BreakStatement/ContinueStatement: Filled with the hole. |
| 1281 // - Falling through into finally-block: Filled with the hole. | 1288 // - Falling through into finally-block: Filled with the hole. |
| 1282 Node* result = try_control.GetResultValueNode(); | 1289 Node* result = try_control.GetResultValueNode(); |
| 1290 Node* token = try_control.GetDispatchTokenNode(); | |
| 1283 | 1291 |
| 1284 // TODO(mstarzinger): See FullCodeGenerator::EnterFinallyBlock. | 1292 // The result value, dispatch token and message is expected on the operand |
| 1285 environment()->Push(jsgraph()->SmiConstant(Code::kHeaderSize)); | 1293 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock). |
| 1294 environment()->Push(token); // TODO(mstarzinger): Cook token! | |
| 1286 environment()->Push(result); | 1295 environment()->Push(result); |
| 1287 environment()->Push(jsgraph()->TheHoleConstant()); // pending_message_obj | 1296 environment()->Push(BuildLoadExternal(message_object, kMachAnyTagged)); |
| 1288 environment()->Push(jsgraph()->SmiConstant(0)); // has_pending_message | 1297 environment()->Push(BuildLoadExternal(message_present, kMachBool)); |
| 1289 environment()->Push(jsgraph()->TheHoleConstant()); // pending_message_script | 1298 environment()->Push(BuildLoadExternal(message_script, kMachAnyTagged)); |
| 1290 | 1299 |
| 1291 // Evaluate the finally-block. | 1300 // Evaluate the finally-block. |
| 1292 Visit(stmt->finally_block()); | 1301 Visit(stmt->finally_block()); |
| 1293 try_control.EndFinally(); | 1302 try_control.EndFinally(); |
| 1294 | 1303 |
| 1295 // TODO(mstarzinger): See FullCodeGenerator::ExitFinallyBlock. | 1304 // The result value, dispatch token and message is restored from the operand |
| 1296 environment()->Drop(5); | 1305 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock). |
| 1306 BuildStoreExternal(message_script, kMachAnyTagged, environment()->Pop()); | |
| 1307 BuildStoreExternal(message_present, kMachBool, environment()->Pop()); | |
| 1308 BuildStoreExternal(message_object, kMachAnyTagged, environment()->Pop()); | |
| 1309 result = environment()->Pop(); | |
| 1310 token = environment()->Pop(); // TODO(mstarzinger): Uncook token! | |
| 1297 | 1311 |
| 1298 // Dynamic dispatch after the finally-block. | 1312 // Dynamic dispatch after the finally-block. |
| 1299 Node* token = try_control.GetDispatchTokenNode(); | |
| 1300 commands->ApplyDeferredCommands(token, result); | 1313 commands->ApplyDeferredCommands(token, result); |
| 1301 | 1314 |
| 1302 // TODO(mstarzinger): Remove bailout once everything works. | 1315 // TODO(mstarzinger): Remove bailout once everything works. |
| 1303 if (!FLAG_turbo_exceptions) SetStackOverflow(); | 1316 if (!FLAG_turbo_exceptions) SetStackOverflow(); |
| 1304 } | 1317 } |
| 1305 | 1318 |
| 1306 | 1319 |
| 1307 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1320 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1308 // TODO(turbofan): Do we really need a separate reloc-info for this? | 1321 // TODO(turbofan): Do we really need a separate reloc-info for this? |
| 1309 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); | 1322 Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0)); |
| (...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2798 | 2811 |
| 2799 | 2812 |
| 2800 Node* AstGraphBuilder::BuildLoadGlobalProxy() { | 2813 Node* AstGraphBuilder::BuildLoadGlobalProxy() { |
| 2801 Node* global = BuildLoadGlobalObject(); | 2814 Node* global = BuildLoadGlobalObject(); |
| 2802 Node* proxy = | 2815 Node* proxy = |
| 2803 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); | 2816 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); |
| 2804 return proxy; | 2817 return proxy; |
| 2805 } | 2818 } |
| 2806 | 2819 |
| 2807 | 2820 |
| 2821 Node* AstGraphBuilder::BuildLoadExternal(ExternalReference reference, | |
| 2822 MachineType type) { | |
| 2823 return NewNode(jsgraph()->machine()->Load(type), | |
| 2824 jsgraph()->ExternalConstant(reference), | |
| 2825 jsgraph()->ZeroConstant()); | |
|
Benedikt Meurer
2015/03/06 04:50:49
This is probably wrong for the generic pipeline an
Michael Starzinger
2015/03/06 09:47:36
Done.
| |
| 2826 } | |
| 2827 | |
| 2828 | |
| 2829 Node* AstGraphBuilder::BuildStoreExternal(ExternalReference reference, | |
| 2830 MachineType type, Node* value) { | |
| 2831 StoreRepresentation representation(type, kNoWriteBarrier); | |
| 2832 return NewNode(jsgraph()->machine()->Store(representation), | |
| 2833 jsgraph()->ExternalConstant(reference), | |
| 2834 jsgraph()->ZeroConstant(), value); | |
|
Benedikt Meurer
2015/03/06 04:50:49
Same here.
Michael Starzinger
2015/03/06 09:47:36
Done.
| |
| 2835 } | |
| 2836 | |
| 2837 | |
| 2808 Node* AstGraphBuilder::BuildToBoolean(Node* input) { | 2838 Node* AstGraphBuilder::BuildToBoolean(Node* input) { |
| 2809 // TODO(titzer): This should be in a JSOperatorReducer. | 2839 // TODO(titzer): This should be in a JSOperatorReducer. |
| 2810 switch (input->opcode()) { | 2840 switch (input->opcode()) { |
| 2811 case IrOpcode::kInt32Constant: | 2841 case IrOpcode::kInt32Constant: |
| 2812 return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0)); | 2842 return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0)); |
| 2813 case IrOpcode::kFloat64Constant: | 2843 case IrOpcode::kFloat64Constant: |
| 2814 return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0)); | 2844 return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0)); |
| 2815 case IrOpcode::kNumberConstant: | 2845 case IrOpcode::kNumberConstant: |
| 2816 return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0)); | 2846 return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0)); |
| 2817 case IrOpcode::kHeapConstant: { | 2847 case IrOpcode::kHeapConstant: { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2933 default: | 2963 default: |
| 2934 UNREACHABLE(); | 2964 UNREACHABLE(); |
| 2935 js_op = NULL; | 2965 js_op = NULL; |
| 2936 } | 2966 } |
| 2937 return NewNode(js_op, left, right); | 2967 return NewNode(js_op, left, right); |
| 2938 } | 2968 } |
| 2939 | 2969 |
| 2940 | 2970 |
| 2941 Node* AstGraphBuilder::BuildStackCheck() { | 2971 Node* AstGraphBuilder::BuildStackCheck() { |
| 2942 IfBuilder stack_check(this); | 2972 IfBuilder stack_check(this); |
| 2943 Node* limit = | 2973 Node* limit = BuildLoadExternal( |
| 2944 NewNode(jsgraph()->machine()->Load(kMachPtr), | 2974 ExternalReference::address_of_stack_limit(isolate()), kMachPtr); |
| 2945 jsgraph()->ExternalConstant( | |
| 2946 ExternalReference::address_of_stack_limit(isolate())), | |
| 2947 jsgraph()->ZeroConstant()); | |
| 2948 Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer()); | 2975 Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer()); |
| 2949 Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack); | 2976 Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack); |
| 2950 stack_check.If(tag, BranchHint::kTrue); | 2977 stack_check.If(tag, BranchHint::kTrue); |
| 2951 stack_check.Then(); | 2978 stack_check.Then(); |
| 2952 stack_check.Else(); | 2979 stack_check.Else(); |
| 2953 Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0)); | 2980 Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0)); |
| 2954 stack_check.End(); | 2981 stack_check.End(); |
| 2955 return guard; | 2982 return guard; |
| 2956 } | 2983 } |
| 2957 | 2984 |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3258 // Phi does not exist yet, introduce one. | 3285 // Phi does not exist yet, introduce one. |
| 3259 value = NewPhi(inputs, value, control); | 3286 value = NewPhi(inputs, value, control); |
| 3260 value->ReplaceInput(inputs - 1, other); | 3287 value->ReplaceInput(inputs - 1, other); |
| 3261 } | 3288 } |
| 3262 return value; | 3289 return value; |
| 3263 } | 3290 } |
| 3264 | 3291 |
| 3265 } // namespace compiler | 3292 } // namespace compiler |
| 3266 } // namespace internal | 3293 } // namespace internal |
| 3267 } // namespace v8 | 3294 } // namespace v8 |
| OLD | NEW |