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 1459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2769 PrepareFrameState(store, bailout_id, combine); | 2782 PrepareFrameState(store, bailout_id, combine); |
2770 return store; | 2783 return store; |
2771 } | 2784 } |
2772 } | 2785 } |
2773 UNREACHABLE(); | 2786 UNREACHABLE(); |
2774 return NULL; | 2787 return NULL; |
2775 } | 2788 } |
2776 | 2789 |
2777 | 2790 |
2778 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { | 2791 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) { |
2779 Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, | 2792 return NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object, |
2780 jsgraph()->Int32Constant(offset - kHeapObjectTag)); | 2793 jsgraph()->IntPtrConstant(offset - kHeapObjectTag)); |
2781 return field_load; | |
2782 } | 2794 } |
2783 | 2795 |
2784 | 2796 |
2785 Node* AstGraphBuilder::BuildLoadBuiltinsObject() { | 2797 Node* AstGraphBuilder::BuildLoadBuiltinsObject() { |
2786 Node* global = BuildLoadGlobalObject(); | 2798 Node* global = BuildLoadGlobalObject(); |
2787 Node* builtins = | 2799 Node* builtins = |
2788 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); | 2800 BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset); |
2789 return builtins; | 2801 return builtins; |
2790 } | 2802 } |
2791 | 2803 |
2792 | 2804 |
2793 Node* AstGraphBuilder::BuildLoadGlobalObject() { | 2805 Node* AstGraphBuilder::BuildLoadGlobalObject() { |
2794 const Operator* load_op = | 2806 const Operator* load_op = |
2795 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); | 2807 javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true); |
2796 return NewNode(load_op, function_context_.get()); | 2808 return NewNode(load_op, function_context_.get()); |
2797 } | 2809 } |
2798 | 2810 |
2799 | 2811 |
2800 Node* AstGraphBuilder::BuildLoadGlobalProxy() { | 2812 Node* AstGraphBuilder::BuildLoadGlobalProxy() { |
2801 Node* global = BuildLoadGlobalObject(); | 2813 Node* global = BuildLoadGlobalObject(); |
2802 Node* proxy = | 2814 Node* proxy = |
2803 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); | 2815 BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset); |
2804 return proxy; | 2816 return proxy; |
2805 } | 2817 } |
2806 | 2818 |
2807 | 2819 |
| 2820 Node* AstGraphBuilder::BuildLoadExternal(ExternalReference reference, |
| 2821 MachineType type) { |
| 2822 return NewNode(jsgraph()->machine()->Load(type), |
| 2823 jsgraph()->ExternalConstant(reference), |
| 2824 jsgraph()->IntPtrConstant(0)); |
| 2825 } |
| 2826 |
| 2827 |
| 2828 Node* AstGraphBuilder::BuildStoreExternal(ExternalReference reference, |
| 2829 MachineType type, Node* value) { |
| 2830 StoreRepresentation representation(type, kNoWriteBarrier); |
| 2831 return NewNode(jsgraph()->machine()->Store(representation), |
| 2832 jsgraph()->ExternalConstant(reference), |
| 2833 jsgraph()->IntPtrConstant(0), value); |
| 2834 } |
| 2835 |
| 2836 |
2808 Node* AstGraphBuilder::BuildToBoolean(Node* input) { | 2837 Node* AstGraphBuilder::BuildToBoolean(Node* input) { |
2809 // TODO(titzer): This should be in a JSOperatorReducer. | 2838 // TODO(titzer): This should be in a JSOperatorReducer. |
2810 switch (input->opcode()) { | 2839 switch (input->opcode()) { |
2811 case IrOpcode::kInt32Constant: | 2840 case IrOpcode::kInt32Constant: |
2812 return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0)); | 2841 return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0)); |
2813 case IrOpcode::kFloat64Constant: | 2842 case IrOpcode::kFloat64Constant: |
2814 return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0)); | 2843 return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0)); |
2815 case IrOpcode::kNumberConstant: | 2844 case IrOpcode::kNumberConstant: |
2816 return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0)); | 2845 return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0)); |
2817 case IrOpcode::kHeapConstant: { | 2846 case IrOpcode::kHeapConstant: { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2933 default: | 2962 default: |
2934 UNREACHABLE(); | 2963 UNREACHABLE(); |
2935 js_op = NULL; | 2964 js_op = NULL; |
2936 } | 2965 } |
2937 return NewNode(js_op, left, right); | 2966 return NewNode(js_op, left, right); |
2938 } | 2967 } |
2939 | 2968 |
2940 | 2969 |
2941 Node* AstGraphBuilder::BuildStackCheck() { | 2970 Node* AstGraphBuilder::BuildStackCheck() { |
2942 IfBuilder stack_check(this); | 2971 IfBuilder stack_check(this); |
2943 Node* limit = | 2972 Node* limit = BuildLoadExternal( |
2944 NewNode(jsgraph()->machine()->Load(kMachPtr), | 2973 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()); | 2974 Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer()); |
2949 Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack); | 2975 Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack); |
2950 stack_check.If(tag, BranchHint::kTrue); | 2976 stack_check.If(tag, BranchHint::kTrue); |
2951 stack_check.Then(); | 2977 stack_check.Then(); |
2952 stack_check.Else(); | 2978 stack_check.Else(); |
2953 Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0)); | 2979 Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0)); |
2954 stack_check.End(); | 2980 stack_check.End(); |
2955 return guard; | 2981 return guard; |
2956 } | 2982 } |
2957 | 2983 |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3258 // Phi does not exist yet, introduce one. | 3284 // Phi does not exist yet, introduce one. |
3259 value = NewPhi(inputs, value, control); | 3285 value = NewPhi(inputs, value, control); |
3260 value->ReplaceInput(inputs - 1, other); | 3286 value->ReplaceInput(inputs - 1, other); |
3261 } | 3287 } |
3262 return value; | 3288 return value; |
3263 } | 3289 } |
3264 | 3290 |
3265 } // namespace compiler | 3291 } // namespace compiler |
3266 } // namespace internal | 3292 } // namespace internal |
3267 } // namespace v8 | 3293 } // namespace v8 |
OLD | NEW |