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 |