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/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
| 6 #include "src/compiler/js-graph.h" | 6 #include "src/compiler/js-graph.h" |
| 7 #include "src/compiler/js-typed-lowering.h" | 7 #include "src/compiler/js-typed-lowering.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/operator-properties.h" | 10 #include "src/compiler/operator-properties.h" |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 // Avoid introducing too many eager ToString() operations. | 204 // Avoid introducing too many eager ToString() operations. |
| 205 Reduction reduced = lowering_->ReduceJSToStringInput(node); | 205 Reduction reduced = lowering_->ReduceJSToStringInput(node); |
| 206 if (reduced.Changed()) return reduced.replacement(); | 206 if (reduced.Changed()) return reduced.replacement(); |
| 207 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), | 207 Node* n = graph()->NewNode(javascript()->ToString(), node, context(), |
| 208 effect(), control()); | 208 effect(), control()); |
| 209 update_effect(n); | 209 update_effect(n); |
| 210 return n; | 210 return n; |
| 211 } | 211 } |
| 212 | 212 |
| 213 Node* CreateFrameStateForLeftInput(Node* frame_state) { | 213 Node* CreateFrameStateForLeftInput(Node* frame_state) { |
| 214 if (!FLAG_turbo_deoptimization) return nullptr; | 214 // TODO(bmeurer): if (!FLAG_turbo_deoptimization) return nullptr; |
|
Jarin
2015/04/23 08:33:08
Remove the TODO and perhaps consider short-circuit
Benedikt Meurer
2015/04/23 08:35:34
Done.
| |
| 215 | 215 |
| 216 FrameStateCallInfo state_info = | 216 FrameStateCallInfo state_info = |
| 217 OpParameter<FrameStateCallInfo>(frame_state); | 217 OpParameter<FrameStateCallInfo>(frame_state); |
| 218 // If the frame state is already the right one, just return it. | 218 // If the frame state is already the right one, just return it. |
| 219 if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt && | 219 if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt && |
| 220 state_info.state_combine().GetOffsetToPokeAt() == 1) { | 220 state_info.state_combine().GetOffsetToPokeAt() == 1) { |
| 221 return frame_state; | 221 return frame_state; |
| 222 } | 222 } |
| 223 | 223 |
| 224 // Here, we smash the result of the conversion into the slot just below | 224 // Here, we smash the result of the conversion into the slot just below |
| 225 // the stack top. This is the slot that full code uses to store the | 225 // the stack top. This is the slot that full code uses to store the |
| 226 // left operand. | 226 // left operand. |
| 227 const Operator* op = jsgraph()->common()->FrameState( | 227 const Operator* op = jsgraph()->common()->FrameState( |
| 228 state_info.type(), state_info.bailout_id(), | 228 state_info.type(), state_info.bailout_id(), |
| 229 OutputFrameStateCombine::PokeAt(1)); | 229 OutputFrameStateCombine::PokeAt(1)); |
| 230 | 230 |
| 231 return graph()->NewNode(op, frame_state->InputAt(0), | 231 return graph()->NewNode(op, frame_state->InputAt(0), |
| 232 frame_state->InputAt(1), frame_state->InputAt(2), | 232 frame_state->InputAt(1), frame_state->InputAt(2), |
| 233 frame_state->InputAt(3), frame_state->InputAt(4)); | 233 frame_state->InputAt(3), frame_state->InputAt(4)); |
| 234 } | 234 } |
| 235 | 235 |
| 236 Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) { | 236 Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) { |
| 237 if (!FLAG_turbo_deoptimization) return nullptr; | 237 // TODO(bmeurer): if (!FLAG_turbo_deoptimization) return nullptr; |
|
Jarin
2015/04/23 08:33:08
Remove the TODO.
Benedikt Meurer
2015/04/23 08:35:35
Done.
| |
| 238 | 238 |
| 239 FrameStateCallInfo state_info = | 239 FrameStateCallInfo state_info = |
| 240 OpParameter<FrameStateCallInfo>(frame_state); | 240 OpParameter<FrameStateCallInfo>(frame_state); |
| 241 | 241 |
| 242 if (state_info.bailout_id() == BailoutId::None()) { | 242 if (state_info.bailout_id() == BailoutId::None()) { |
| 243 // Dummy frame state => just leave it as is. | 243 // Dummy frame state => just leave it as is. |
| 244 return frame_state; | 244 return frame_state; |
| 245 } | 245 } |
| 246 | 246 |
| 247 // Create a frame state that stores the result of the operation to the | 247 // Create a frame state that stores the result of the operation to the |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 272 frame_state->InputAt(3), frame_state->InputAt(4)); | 272 frame_state->InputAt(3), frame_state->InputAt(4)); |
| 273 } | 273 } |
| 274 | 274 |
| 275 Node* ConvertPrimitiveToNumber(Node* node) { | 275 Node* ConvertPrimitiveToNumber(Node* node) { |
| 276 return lowering_->ConvertPrimitiveToNumber(node); | 276 return lowering_->ConvertPrimitiveToNumber(node); |
| 277 } | 277 } |
| 278 | 278 |
| 279 Node* ConvertToNumber(Node* node, Node* frame_state) { | 279 Node* ConvertToNumber(Node* node, Node* frame_state) { |
| 280 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { | 280 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { |
| 281 return ConvertPrimitiveToNumber(node); | 281 return ConvertPrimitiveToNumber(node); |
| 282 } else if (!FLAG_turbo_deoptimization) { | |
| 283 // We cannot use ConvertToPrimitiveNumber here because we need context | |
| 284 // for converting general values. | |
| 285 Node* const n = graph()->NewNode(javascript()->ToNumber(), node, | |
| 286 context(), effect(), control()); | |
| 287 update_effect(n); | |
| 288 return n; | |
| 289 } else { | 282 } else { |
| 290 Node* const n = | 283 Node* const n = |
| 291 graph()->NewNode(javascript()->ToNumber(), node, context(), | 284 graph()->NewNode(javascript()->ToNumber(), node, context(), |
| 292 frame_state, effect(), control()); | 285 frame_state, effect(), control()); |
| 293 update_effect(n); | 286 update_effect(n); |
| 294 return n; | 287 return n; |
| 295 } | 288 } |
| 296 } | 289 } |
| 297 | 290 |
| 298 Node* ConvertToUI32(Node* node, Signedness signedness) { | 291 Node* ConvertToUI32(Node* node, Signedness signedness) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 318 | 311 |
| 319 | 312 |
| 320 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 313 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
| 321 JSBinopReduction r(this, node); | 314 JSBinopReduction r(this, node); |
| 322 if (r.BothInputsAre(Type::Number())) { | 315 if (r.BothInputsAre(Type::Number())) { |
| 323 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 316 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
| 324 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 317 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| 325 } | 318 } |
| 326 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { | 319 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { |
| 327 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 320 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
| 328 Node* frame_state = FLAG_turbo_deoptimization | 321 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 329 ? NodeProperties::GetFrameStateInput(node, 1) | |
| 330 : nullptr; | |
| 331 r.ConvertInputsToNumber(frame_state); | 322 r.ConvertInputsToNumber(frame_state); |
| 332 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); | 323 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
| 333 } | 324 } |
| 334 #if 0 | 325 #if 0 |
| 335 // TODO(turbofan): Lowering of StringAdd is disabled for now because: | 326 // TODO(turbofan): Lowering of StringAdd is disabled for now because: |
| 336 // a) The inserted ToString operation screws up valueOf vs. toString order. | 327 // a) The inserted ToString operation screws up valueOf vs. toString order. |
| 337 // b) Deoptimization at ToString doesn't have corresponding bailout id. | 328 // b) Deoptimization at ToString doesn't have corresponding bailout id. |
| 338 // c) Our current StringAddStub is actually non-pure and requires context. | 329 // c) Our current StringAddStub is actually non-pure and requires context. |
| 339 if (r.OneInputIs(Type::String())) { | 330 if (r.OneInputIs(Type::String())) { |
| 340 // JSAdd(x:string, y:string) => StringAdd(x, y) | 331 // JSAdd(x:string, y:string) => StringAdd(x, y) |
| 341 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) | 332 // JSAdd(x:string, y) => StringAdd(x, ToString(y)) |
| 342 // JSAdd(x, y:string) => StringAdd(ToString(x), y) | 333 // JSAdd(x, y:string) => StringAdd(ToString(x), y) |
| 343 r.ConvertInputsToString(); | 334 r.ConvertInputsToString(); |
| 344 return r.ChangeToPureOperator(simplified()->StringAdd()); | 335 return r.ChangeToPureOperator(simplified()->StringAdd()); |
| 345 } | 336 } |
| 346 #endif | 337 #endif |
| 347 return NoChange(); | 338 return NoChange(); |
| 348 } | 339 } |
| 349 | 340 |
| 350 | 341 |
| 351 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, | 342 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
| 352 const Operator* numberOp) { | 343 const Operator* numberOp) { |
| 353 JSBinopReduction r(this, node); | 344 JSBinopReduction r(this, node); |
| 354 Node* frame_state = FLAG_turbo_deoptimization | 345 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 355 ? NodeProperties::GetFrameStateInput(node, 1) | |
| 356 : nullptr; | |
| 357 r.ConvertInputsToNumber(frame_state); | 346 r.ConvertInputsToNumber(frame_state); |
| 358 return r.ChangeToPureOperator(numberOp, Type::Number()); | 347 return r.ChangeToPureOperator(numberOp, Type::Number()); |
| 359 } | 348 } |
| 360 | 349 |
| 361 | 350 |
| 362 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { | 351 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { |
| 363 JSBinopReduction r(this, node); | 352 JSBinopReduction r(this, node); |
| 364 Node* frame_state = FLAG_turbo_deoptimization | 353 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 365 ? NodeProperties::GetFrameStateInput(node, 1) | |
| 366 : nullptr; | |
| 367 r.ConvertInputsToNumber(frame_state); | 354 r.ConvertInputsToNumber(frame_state); |
| 368 r.ConvertInputsToUI32(kSigned, kSigned); | 355 r.ConvertInputsToUI32(kSigned, kSigned); |
| 369 return r.ChangeToPureOperator(intOp, Type::Integral32()); | 356 return r.ChangeToPureOperator(intOp, Type::Integral32()); |
| 370 } | 357 } |
| 371 | 358 |
| 372 | 359 |
| 373 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, | 360 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, |
| 374 Signedness left_signedness, | 361 Signedness left_signedness, |
| 375 const Operator* shift_op) { | 362 const Operator* shift_op) { |
| 376 JSBinopReduction r(this, node); | 363 JSBinopReduction r(this, node); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 if (NodeProperties::GetContextInput(node) != | 680 if (NodeProperties::GetContextInput(node) != |
| 694 jsgraph()->NoContextConstant() || | 681 jsgraph()->NoContextConstant() || |
| 695 NodeProperties::GetEffectInput(node) != graph()->start() || | 682 NodeProperties::GetEffectInput(node) != graph()->start() || |
| 696 NodeProperties::GetControlInput(node) != graph()->start()) { | 683 NodeProperties::GetControlInput(node) != graph()->start()) { |
| 697 // JSToNumber(x:plain-primitive,context,effect,control) | 684 // JSToNumber(x:plain-primitive,context,effect,control) |
| 698 // => JSToNumber(x,no-context,start,start) | 685 // => JSToNumber(x,no-context,start,start) |
| 699 RelaxEffectsAndControls(node); | 686 RelaxEffectsAndControls(node); |
| 700 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); | 687 NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant()); |
| 701 NodeProperties::ReplaceControlInput(node, graph()->start()); | 688 NodeProperties::ReplaceControlInput(node, graph()->start()); |
| 702 NodeProperties::ReplaceEffectInput(node, graph()->start()); | 689 NodeProperties::ReplaceEffectInput(node, graph()->start()); |
| 703 if (FLAG_turbo_deoptimization) { | 690 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
| 704 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 691 NodeProperties::ReplaceFrameStateInput(node, 0, |
| 705 NodeProperties::ReplaceFrameStateInput(node, 0, | 692 jsgraph()->EmptyFrameState()); |
| 706 jsgraph()->EmptyFrameState()); | |
| 707 } | |
| 708 return Changed(node); | 693 return Changed(node); |
| 709 } | 694 } |
| 710 } | 695 } |
| 711 return NoChange(); | 696 return NoChange(); |
| 712 } | 697 } |
| 713 | 698 |
| 714 | 699 |
| 715 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 700 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
| 716 if (input->opcode() == IrOpcode::kJSToString) { | 701 if (input->opcode() == IrOpcode::kJSToString) { |
| 717 // Recursively try to reduce the input first. | 702 // Recursively try to reduce the input first. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 834 Node* length = jsgraph()->Constant(byte_length); | 819 Node* length = jsgraph()->Constant(byte_length); |
| 835 Node* context = NodeProperties::GetContextInput(node); | 820 Node* context = NodeProperties::GetContextInput(node); |
| 836 Node* effect = NodeProperties::GetEffectInput(node); | 821 Node* effect = NodeProperties::GetEffectInput(node); |
| 837 Node* control = NodeProperties::GetControlInput(node); | 822 Node* control = NodeProperties::GetControlInput(node); |
| 838 // Convert to a number first. | 823 // Convert to a number first. |
| 839 if (!value_type->Is(Type::Number())) { | 824 if (!value_type->Is(Type::Number())) { |
| 840 Reduction number_reduction = ReduceJSToNumberInput(value); | 825 Reduction number_reduction = ReduceJSToNumberInput(value); |
| 841 if (number_reduction.Changed()) { | 826 if (number_reduction.Changed()) { |
| 842 value = number_reduction.replacement(); | 827 value = number_reduction.replacement(); |
| 843 } else { | 828 } else { |
| 844 DCHECK(FLAG_turbo_deoptimization == | 829 Node* frame_state_for_to_number = |
| 845 (OperatorProperties::GetFrameStateInputCount( | 830 NodeProperties::GetFrameStateInput(node, 1); |
| 846 javascript()->ToNumber()) == 1)); | 831 value = effect = |
| 847 if (FLAG_turbo_deoptimization) { | 832 graph()->NewNode(javascript()->ToNumber(), value, context, |
| 848 Node* frame_state_for_to_number = | 833 frame_state_for_to_number, effect, control); |
| 849 NodeProperties::GetFrameStateInput(node, 1); | |
| 850 value = effect = | |
| 851 graph()->NewNode(javascript()->ToNumber(), value, context, | |
| 852 frame_state_for_to_number, effect, control); | |
| 853 } else { | |
| 854 value = effect = graph()->NewNode(javascript()->ToNumber(), value, | |
| 855 context, effect, control); | |
| 856 } | |
| 857 } | 834 } |
| 858 } | 835 } |
| 859 // For integer-typed arrays, convert to the integer type. | 836 // For integer-typed arrays, convert to the integer type. |
| 860 if (TypeOf(access.machine_type()) == kTypeInt32 && | 837 if (TypeOf(access.machine_type()) == kTypeInt32 && |
| 861 !value_type->Is(Type::Signed32())) { | 838 !value_type->Is(Type::Signed32())) { |
| 862 value = graph()->NewNode(simplified()->NumberToInt32(), value); | 839 value = graph()->NewNode(simplified()->NumberToInt32(), value); |
| 863 } else if (TypeOf(access.machine_type()) == kTypeUint32 && | 840 } else if (TypeOf(access.machine_type()) == kTypeUint32 && |
| 864 !value_type->Is(Type::Unsigned32())) { | 841 !value_type->Is(Type::Unsigned32())) { |
| 865 value = graph()->NewNode(simplified()->NumberToUint32(), value); | 842 value = graph()->NewNode(simplified()->NumberToUint32(), value); |
| 866 } | 843 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1029 return NoChange(); | 1006 return NoChange(); |
| 1030 } | 1007 } |
| 1031 | 1008 |
| 1032 | 1009 |
| 1033 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { | 1010 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) { |
| 1034 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); | 1011 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive())); |
| 1035 // Avoid inserting too many eager ToNumber() operations. | 1012 // Avoid inserting too many eager ToNumber() operations. |
| 1036 Reduction const reduction = ReduceJSToNumberInput(input); | 1013 Reduction const reduction = ReduceJSToNumberInput(input); |
| 1037 if (reduction.Changed()) return reduction.replacement(); | 1014 if (reduction.Changed()) return reduction.replacement(); |
| 1038 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. | 1015 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. |
| 1039 Node* const conversion = | 1016 Node* const conversion = graph()->NewNode( |
| 1040 FLAG_turbo_deoptimization | 1017 javascript()->ToNumber(), input, jsgraph()->NoContextConstant(), |
| 1041 ? graph()->NewNode(javascript()->ToNumber(), input, | 1018 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start()); |
| 1042 jsgraph()->NoContextConstant(), | |
| 1043 jsgraph()->EmptyFrameState(), graph()->start(), | |
| 1044 graph()->start()) | |
| 1045 : graph()->NewNode(javascript()->ToNumber(), input, | |
| 1046 jsgraph()->NoContextConstant(), graph()->start(), | |
| 1047 graph()->start()); | |
| 1048 InsertConversion(conversion); | 1019 InsertConversion(conversion); |
| 1049 return conversion; | 1020 return conversion; |
| 1050 } | 1021 } |
| 1051 | 1022 |
| 1052 | 1023 |
| 1053 template <IrOpcode::Value kOpcode> | 1024 template <IrOpcode::Value kOpcode> |
| 1054 Node* JSTypedLowering::FindConversion(Node* input) { | 1025 Node* JSTypedLowering::FindConversion(Node* input) { |
| 1055 size_t const input_id = input->id(); | 1026 size_t const input_id = input->id(); |
| 1056 if (input_id < conversions_.size()) { | 1027 if (input_id < conversions_.size()) { |
| 1057 Node* const conversion = conversions_[input_id]; | 1028 Node* const conversion = conversions_[input_id]; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 } | 1067 } |
| 1097 | 1068 |
| 1098 | 1069 |
| 1099 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1070 MachineOperatorBuilder* JSTypedLowering::machine() const { |
| 1100 return jsgraph()->machine(); | 1071 return jsgraph()->machine(); |
| 1101 } | 1072 } |
| 1102 | 1073 |
| 1103 } // namespace compiler | 1074 } // namespace compiler |
| 1104 } // namespace internal | 1075 } // namespace internal |
| 1105 } // namespace v8 | 1076 } // namespace v8 |
| OLD | NEW |