OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 "hydrogen.h" | 5 #include "hydrogen.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "v8.h" | 9 #include "v8.h" |
10 #include "allocation-site-scopes.h" | 10 #include "allocation-site-scopes.h" |
(...skipping 1708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1719 // Load the value in case of cache hit. | 1719 // Load the value in case of cache hit. |
1720 HValue* key_index = Pop(); | 1720 HValue* key_index = Pop(); |
1721 HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1()); | 1721 HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1()); |
1722 Push(Add<HLoadKeyed>(number_string_cache, value_index, | 1722 Push(Add<HLoadKeyed>(number_string_cache, value_index, |
1723 static_cast<HValue*>(NULL), | 1723 static_cast<HValue*>(NULL), |
1724 FAST_ELEMENTS, ALLOW_RETURN_HOLE)); | 1724 FAST_ELEMENTS, ALLOW_RETURN_HOLE)); |
1725 } | 1725 } |
1726 if_found.Else(); | 1726 if_found.Else(); |
1727 { | 1727 { |
1728 // Cache miss, fallback to runtime. | 1728 // Cache miss, fallback to runtime. |
1729 Add<HPushArgument>(object); | 1729 Add<HPushArguments>(zone(), object); |
1730 Push(Add<HCallRuntime>( | 1730 Push(Add<HCallRuntime>( |
1731 isolate()->factory()->empty_string(), | 1731 isolate()->factory()->empty_string(), |
1732 Runtime::FunctionForId(Runtime::kHiddenNumberToStringSkipCache), | 1732 Runtime::FunctionForId(Runtime::kHiddenNumberToStringSkipCache), |
1733 1)); | 1733 1)); |
1734 } | 1734 } |
1735 if_found.End(); | 1735 if_found.End(); |
1736 | 1736 |
1737 return Pop(); | 1737 return Pop(); |
1738 } | 1738 } |
1739 | 1739 |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2043 | 2043 |
2044 // Count the native string addition. | 2044 // Count the native string addition. |
2045 AddIncrementCounter(isolate()->counters()->string_add_native()); | 2045 AddIncrementCounter(isolate()->counters()->string_add_native()); |
2046 | 2046 |
2047 // Return the sequential string. | 2047 // Return the sequential string. |
2048 Push(result); | 2048 Push(result); |
2049 } | 2049 } |
2050 if_sameencodingandsequential.Else(); | 2050 if_sameencodingandsequential.Else(); |
2051 { | 2051 { |
2052 // Fallback to the runtime to add the two strings. | 2052 // Fallback to the runtime to add the two strings. |
2053 Add<HPushArgument>(left); | 2053 Add<HPushArguments>(zone(), left, right); |
2054 Add<HPushArgument>(right); | |
2055 Push(Add<HCallRuntime>( | 2054 Push(Add<HCallRuntime>( |
2056 isolate()->factory()->empty_string(), | 2055 isolate()->factory()->empty_string(), |
2057 Runtime::FunctionForId(Runtime::kHiddenStringAdd), | 2056 Runtime::FunctionForId(Runtime::kHiddenStringAdd), |
2058 2)); | 2057 2)); |
2059 } | 2058 } |
2060 if_sameencodingandsequential.End(); | 2059 if_sameencodingandsequential.End(); |
2061 } | 2060 } |
2062 if_createcons.End(); | 2061 if_createcons.End(); |
2063 | 2062 |
2064 return Pop(); | 2063 return Pop(); |
(...skipping 2116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4181 } | 4180 } |
4182 } | 4181 } |
4183 | 4182 |
4184 | 4183 |
4185 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) { | 4184 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) { |
4186 ZoneList<HValue*> arguments(count, zone()); | 4185 ZoneList<HValue*> arguments(count, zone()); |
4187 for (int i = 0; i < count; ++i) { | 4186 for (int i = 0; i < count; ++i) { |
4188 arguments.Add(Pop(), zone()); | 4187 arguments.Add(Pop(), zone()); |
4189 } | 4188 } |
4190 | 4189 |
| 4190 HPushArguments* push_args = New<HPushArguments>(zone()); |
4191 while (!arguments.is_empty()) { | 4191 while (!arguments.is_empty()) { |
4192 Add<HPushArgument>(arguments.RemoveLast()); | 4192 push_args->AddArgument(arguments.RemoveLast()); |
4193 } | 4193 } |
| 4194 AddInstruction(push_args); |
4194 } | 4195 } |
4195 | 4196 |
4196 | 4197 |
4197 template <class Instruction> | 4198 template <class Instruction> |
4198 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 4199 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
4199 PushArgumentsFromEnvironment(call->argument_count()); | 4200 PushArgumentsFromEnvironment(call->argument_count()); |
4200 return call; | 4201 return call; |
4201 } | 4202 } |
4202 | 4203 |
4203 | 4204 |
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5177 } else { | 5178 } else { |
5178 NoObservableSideEffectsScope no_effects(this); | 5179 NoObservableSideEffectsScope no_effects(this); |
5179 Handle<FixedArray> closure_literals(closure->literals(), isolate()); | 5180 Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
5180 Handle<FixedArray> constant_properties = expr->constant_properties(); | 5181 Handle<FixedArray> constant_properties = expr->constant_properties(); |
5181 int literal_index = expr->literal_index(); | 5182 int literal_index = expr->literal_index(); |
5182 int flags = expr->fast_elements() | 5183 int flags = expr->fast_elements() |
5183 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; | 5184 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; |
5184 flags |= expr->has_function() | 5185 flags |= expr->has_function() |
5185 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; | 5186 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; |
5186 | 5187 |
5187 Add<HPushArgument>(Add<HConstant>(closure_literals)); | 5188 Add<HPushArguments>(zone(), |
5188 Add<HPushArgument>(Add<HConstant>(literal_index)); | 5189 Add<HConstant>(closure_literals), |
5189 Add<HPushArgument>(Add<HConstant>(constant_properties)); | 5190 Add<HConstant>(literal_index), |
5190 Add<HPushArgument>(Add<HConstant>(flags)); | 5191 Add<HConstant>(constant_properties), |
| 5192 Add<HConstant>(flags)); |
5191 | 5193 |
5192 // TODO(mvstanton): Add a flag to turn off creation of any | 5194 // TODO(mvstanton): Add a flag to turn off creation of any |
5193 // AllocationMementos for this call: we are in crankshaft and should have | 5195 // AllocationMementos for this call: we are in crankshaft and should have |
5194 // learned enough about transition behavior to stop emitting mementos. | 5196 // learned enough about transition behavior to stop emitting mementos. |
5195 Runtime::FunctionId function_id = Runtime::kHiddenCreateObjectLiteral; | 5197 Runtime::FunctionId function_id = Runtime::kHiddenCreateObjectLiteral; |
5196 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5198 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
5197 Runtime::FunctionForId(function_id), | 5199 Runtime::FunctionForId(function_id), |
5198 4); | 5200 4); |
5199 } | 5201 } |
5200 | 5202 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5335 NoObservableSideEffectsScope no_effects(this); | 5337 NoObservableSideEffectsScope no_effects(this); |
5336 // Boilerplate already exists and constant elements are never accessed, | 5338 // Boilerplate already exists and constant elements are never accessed, |
5337 // pass an empty fixed array to the runtime function instead. | 5339 // pass an empty fixed array to the runtime function instead. |
5338 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 5340 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
5339 int literal_index = expr->literal_index(); | 5341 int literal_index = expr->literal_index(); |
5340 int flags = expr->depth() == 1 | 5342 int flags = expr->depth() == 1 |
5341 ? ArrayLiteral::kShallowElements | 5343 ? ArrayLiteral::kShallowElements |
5342 : ArrayLiteral::kNoFlags; | 5344 : ArrayLiteral::kNoFlags; |
5343 flags |= ArrayLiteral::kDisableMementos; | 5345 flags |= ArrayLiteral::kDisableMementos; |
5344 | 5346 |
5345 Add<HPushArgument>(Add<HConstant>(literals)); | 5347 Add<HPushArguments>(zone(), |
5346 Add<HPushArgument>(Add<HConstant>(literal_index)); | 5348 Add<HConstant>(literals), |
5347 Add<HPushArgument>(Add<HConstant>(constants)); | 5349 Add<HConstant>(literal_index), |
5348 Add<HPushArgument>(Add<HConstant>(flags)); | 5350 Add<HConstant>(constants), |
| 5351 Add<HConstant>(flags)); |
5349 | 5352 |
5350 // TODO(mvstanton): Consider a flag to turn off creation of any | 5353 // TODO(mvstanton): Consider a flag to turn off creation of any |
5351 // AllocationMementos for this call: we are in crankshaft and should have | 5354 // AllocationMementos for this call: we are in crankshaft and should have |
5352 // learned enough about transition behavior to stop emitting mementos. | 5355 // learned enough about transition behavior to stop emitting mementos. |
5353 Runtime::FunctionId function_id = Runtime::kHiddenCreateArrayLiteral; | 5356 Runtime::FunctionId function_id = Runtime::kHiddenCreateArrayLiteral; |
5354 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5357 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
5355 Runtime::FunctionForId(function_id), | 5358 Runtime::FunctionForId(function_id), |
5356 4); | 5359 4); |
5357 | 5360 |
5358 // De-opt if elements kind changed from boilerplate_elements_kind. | 5361 // De-opt if elements kind changed from boilerplate_elements_kind. |
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6372 ASSERT(current_block() != NULL); | 6375 ASSERT(current_block() != NULL); |
6373 ASSERT(current_block()->HasPredecessor()); | 6376 ASSERT(current_block()->HasPredecessor()); |
6374 // We don't optimize functions with invalid left-hand sides in | 6377 // We don't optimize functions with invalid left-hand sides in |
6375 // assignments, count operations, or for-in. Consequently throw can | 6378 // assignments, count operations, or for-in. Consequently throw can |
6376 // currently only occur in an effect context. | 6379 // currently only occur in an effect context. |
6377 ASSERT(ast_context()->IsEffect()); | 6380 ASSERT(ast_context()->IsEffect()); |
6378 CHECK_ALIVE(VisitForValue(expr->exception())); | 6381 CHECK_ALIVE(VisitForValue(expr->exception())); |
6379 | 6382 |
6380 HValue* value = environment()->Pop(); | 6383 HValue* value = environment()->Pop(); |
6381 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 6384 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
6382 Add<HPushArgument>(value); | 6385 Add<HPushArguments>(zone(), value); |
6383 Add<HCallRuntime>(isolate()->factory()->empty_string(), | 6386 Add<HCallRuntime>(isolate()->factory()->empty_string(), |
6384 Runtime::FunctionForId(Runtime::kHiddenThrow), 1); | 6387 Runtime::FunctionForId(Runtime::kHiddenThrow), 1); |
6385 Add<HSimulate>(expr->id()); | 6388 Add<HSimulate>(expr->id()); |
6386 | 6389 |
6387 // If the throw definitely exits the function, we can finish with a dummy | 6390 // If the throw definitely exits the function, we can finish with a dummy |
6388 // control flow at this point. This is not the case if the throw is inside | 6391 // control flow at this point. This is not the case if the throw is inside |
6389 // an inlined function which may be replaced. | 6392 // an inlined function which may be replaced. |
6390 if (call_context() == NULL) { | 6393 if (call_context() == NULL) { |
6391 FinishExitCurrentBlock(New<HAbnormalExit>()); | 6394 FinishExitCurrentBlock(New<HAbnormalExit>()); |
6392 } | 6395 } |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6774 // Push arguments when entering inlined function. | 6777 // Push arguments when entering inlined function. |
6775 HEnterInlined* entry = function_state()->entry(); | 6778 HEnterInlined* entry = function_state()->entry(); |
6776 entry->set_arguments_pushed(); | 6779 entry->set_arguments_pushed(); |
6777 | 6780 |
6778 HArgumentsObject* arguments = entry->arguments_object(); | 6781 HArgumentsObject* arguments = entry->arguments_object(); |
6779 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); | 6782 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); |
6780 | 6783 |
6781 HInstruction* insert_after = entry; | 6784 HInstruction* insert_after = entry; |
6782 for (int i = 0; i < arguments_values->length(); i++) { | 6785 for (int i = 0; i < arguments_values->length(); i++) { |
6783 HValue* argument = arguments_values->at(i); | 6786 HValue* argument = arguments_values->at(i); |
6784 HInstruction* push_argument = New<HPushArgument>(argument); | 6787 HInstruction* push_argument = New<HPushArguments>(zone(), argument); |
6785 push_argument->InsertAfter(insert_after); | 6788 push_argument->InsertAfter(insert_after); |
6786 insert_after = push_argument; | 6789 insert_after = push_argument; |
6787 } | 6790 } |
6788 | 6791 |
6789 HArgumentsElements* arguments_elements = New<HArgumentsElements>(true); | 6792 HArgumentsElements* arguments_elements = New<HArgumentsElements>(true); |
6790 arguments_elements->ClearFlag(HValue::kUseGVN); | 6793 arguments_elements->ClearFlag(HValue::kUseGVN); |
6791 arguments_elements->InsertAfter(insert_after); | 6794 arguments_elements->InsertAfter(insert_after); |
6792 function_state()->set_arguments_elements(arguments_elements); | 6795 function_state()->set_arguments_elements(arguments_elements); |
6793 } | 6796 } |
6794 | 6797 |
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8069 PushArgumentsFromEnvironment(argc + 1); | 8072 PushArgumentsFromEnvironment(argc + 1); |
8070 // Drop function after call. | 8073 // Drop function after call. |
8071 drop_extra = true; | 8074 drop_extra = true; |
8072 break; | 8075 break; |
8073 case kCallApiGetter: | 8076 case kCallApiGetter: |
8074 // Receiver and prototype chain cannot have changed. | 8077 // Receiver and prototype chain cannot have changed. |
8075 ASSERT_EQ(0, argc); | 8078 ASSERT_EQ(0, argc); |
8076 ASSERT_EQ(NULL, receiver); | 8079 ASSERT_EQ(NULL, receiver); |
8077 // Receiver is on expression stack. | 8080 // Receiver is on expression stack. |
8078 receiver = Pop(); | 8081 receiver = Pop(); |
8079 Add<HPushArgument>(receiver); | 8082 Add<HPushArguments>(zone(), receiver); |
8080 break; | 8083 break; |
8081 case kCallApiSetter: | 8084 case kCallApiSetter: |
8082 { | 8085 { |
8083 is_store = true; | 8086 is_store = true; |
8084 // Receiver and prototype chain cannot have changed. | 8087 // Receiver and prototype chain cannot have changed. |
8085 ASSERT_EQ(1, argc); | 8088 ASSERT_EQ(1, argc); |
8086 ASSERT_EQ(NULL, receiver); | 8089 ASSERT_EQ(NULL, receiver); |
8087 // Receiver and value are on expression stack. | 8090 // Receiver and value are on expression stack. |
8088 HValue* value = Pop(); | 8091 HValue* value = Pop(); |
8089 receiver = Pop(); | 8092 receiver = Pop(); |
8090 Add<HPushArgument>(receiver); | 8093 Add<HPushArguments>(zone(), receiver, value); |
8091 Add<HPushArgument>(value); | |
8092 break; | 8094 break; |
8093 } | 8095 } |
8094 } | 8096 } |
8095 | 8097 |
8096 HValue* holder = NULL; | 8098 HValue* holder = NULL; |
8097 switch (holder_lookup) { | 8099 switch (holder_lookup) { |
8098 case CallOptimization::kHolderFound: | 8100 case CallOptimization::kHolderFound: |
8099 holder = Add<HConstant>(api_holder); | 8101 holder = Add<HConstant>(api_holder); |
8100 break; | 8102 break; |
8101 case CallOptimization::kHolderIsReceiver: | 8103 case CallOptimization::kHolderIsReceiver: |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8649 if (TryInlineConstruct(expr, receiver)) { | 8651 if (TryInlineConstruct(expr, receiver)) { |
8650 // Inlining worked, add a dependency on the initial map to make sure that | 8652 // Inlining worked, add a dependency on the initial map to make sure that |
8651 // this code is deoptimized whenever the initial map of the constructor | 8653 // this code is deoptimized whenever the initial map of the constructor |
8652 // changes. | 8654 // changes. |
8653 Map::AddDependentCompilationInfo( | 8655 Map::AddDependentCompilationInfo( |
8654 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); | 8656 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); |
8655 return; | 8657 return; |
8656 } | 8658 } |
8657 | 8659 |
8658 // TODO(mstarzinger): For now we remove the previous HAllocate and all | 8660 // TODO(mstarzinger): For now we remove the previous HAllocate and all |
8659 // corresponding instructions and instead add HPushArgument for the | 8661 // corresponding instructions and instead add HPushArguments for the |
8660 // arguments in case inlining failed. What we actually should do is for | 8662 // arguments in case inlining failed. What we actually should do is for |
8661 // inlining to try to build a subgraph without mutating the parent graph. | 8663 // inlining to try to build a subgraph without mutating the parent graph. |
8662 HInstruction* instr = current_block()->last(); | 8664 HInstruction* instr = current_block()->last(); |
8663 do { | 8665 do { |
8664 HInstruction* prev_instr = instr->previous(); | 8666 HInstruction* prev_instr = instr->previous(); |
8665 instr->DeleteAndReplaceWith(NULL); | 8667 instr->DeleteAndReplaceWith(NULL); |
8666 instr = prev_instr; | 8668 instr = prev_instr; |
8667 } while (instr != check); | 8669 } while (instr != check); |
8668 environment()->SetExpressionStackAt(receiver_index, function); | 8670 environment()->SetExpressionStackAt(receiver_index, function); |
8669 HInstruction* call = | 8671 HInstruction* call = |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9128 | 9130 |
9129 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 9131 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { |
9130 Property* prop = expr->expression()->AsProperty(); | 9132 Property* prop = expr->expression()->AsProperty(); |
9131 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 9133 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
9132 if (prop != NULL) { | 9134 if (prop != NULL) { |
9133 CHECK_ALIVE(VisitForValue(prop->obj())); | 9135 CHECK_ALIVE(VisitForValue(prop->obj())); |
9134 CHECK_ALIVE(VisitForValue(prop->key())); | 9136 CHECK_ALIVE(VisitForValue(prop->key())); |
9135 HValue* key = Pop(); | 9137 HValue* key = Pop(); |
9136 HValue* obj = Pop(); | 9138 HValue* obj = Pop(); |
9137 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); | 9139 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); |
9138 Add<HPushArgument>(obj); | 9140 Add<HPushArguments>(zone(), |
9139 Add<HPushArgument>(key); | 9141 obj, key, Add<HConstant>(function_strict_mode())); |
9140 Add<HPushArgument>(Add<HConstant>(function_strict_mode())); | |
9141 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 9142 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
9142 // even though we are certain to pass the correct number of arguments here. | 9143 // even though we are certain to pass the correct number of arguments here. |
9143 HInstruction* instr = New<HInvokeFunction>(function, 3); | 9144 HInstruction* instr = New<HInvokeFunction>(function, 3); |
9144 return ast_context()->ReturnInstruction(instr, expr->id()); | 9145 return ast_context()->ReturnInstruction(instr, expr->id()); |
9145 } else if (proxy != NULL) { | 9146 } else if (proxy != NULL) { |
9146 Variable* var = proxy->var(); | 9147 Variable* var = proxy->var(); |
9147 if (var->IsUnallocated()) { | 9148 if (var->IsUnallocated()) { |
9148 Bailout(kDeleteWithGlobalVariable); | 9149 Bailout(kDeleteWithGlobalVariable); |
9149 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 9150 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
9150 // Result of deleting non-global variables is false. 'this' is not | 9151 // Result of deleting non-global variables is false. 'this' is not |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9615 right = BuildCheckString(right); | 9616 right = BuildCheckString(right); |
9616 } | 9617 } |
9617 | 9618 |
9618 // Convert left argument as necessary. | 9619 // Convert left argument as necessary. |
9619 if (left_type->Is(Type::Number())) { | 9620 if (left_type->Is(Type::Number())) { |
9620 ASSERT(right_type->Is(Type::String())); | 9621 ASSERT(right_type->Is(Type::String())); |
9621 left = BuildNumberToString(left, left_type); | 9622 left = BuildNumberToString(left, left_type); |
9622 } else if (!left_type->Is(Type::String())) { | 9623 } else if (!left_type->Is(Type::String())) { |
9623 ASSERT(right_type->Is(Type::String())); | 9624 ASSERT(right_type->Is(Type::String())); |
9624 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); | 9625 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); |
9625 Add<HPushArgument>(left); | 9626 Add<HPushArguments>(zone(), left, right); |
9626 Add<HPushArgument>(right); | |
9627 return AddUncasted<HInvokeFunction>(function, 2); | 9627 return AddUncasted<HInvokeFunction>(function, 2); |
9628 } | 9628 } |
9629 | 9629 |
9630 // Convert right argument as necessary. | 9630 // Convert right argument as necessary. |
9631 if (right_type->Is(Type::Number())) { | 9631 if (right_type->Is(Type::Number())) { |
9632 ASSERT(left_type->Is(Type::String())); | 9632 ASSERT(left_type->Is(Type::String())); |
9633 right = BuildNumberToString(right, right_type); | 9633 right = BuildNumberToString(right, right_type); |
9634 } else if (!right_type->Is(Type::String())) { | 9634 } else if (!right_type->Is(Type::String())) { |
9635 ASSERT(left_type->Is(Type::String())); | 9635 ASSERT(left_type->Is(Type::String())); |
9636 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); | 9636 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); |
9637 Add<HPushArgument>(left); | 9637 Add<HPushArguments>(zone(), left, right); |
9638 Add<HPushArgument>(right); | |
9639 return AddUncasted<HInvokeFunction>(function, 2); | 9638 return AddUncasted<HInvokeFunction>(function, 2); |
9640 } | 9639 } |
9641 | 9640 |
9642 // Fast path for empty constant strings. | 9641 // Fast path for empty constant strings. |
9643 if (left->IsConstant() && | 9642 if (left->IsConstant() && |
9644 HConstant::cast(left)->HasStringValue() && | 9643 HConstant::cast(left)->HasStringValue() && |
9645 HConstant::cast(left)->StringValue()->length() == 0) { | 9644 HConstant::cast(left)->StringValue()->length() == 0) { |
9646 return right; | 9645 return right; |
9647 } | 9646 } |
9648 if (right->IsConstant() && | 9647 if (right->IsConstant() && |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9690 | 9689 |
9691 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 9690 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
9692 (right_rep.IsTagged() && !right_rep.IsSmi()); | 9691 (right_rep.IsTagged() && !right_rep.IsSmi()); |
9693 | 9692 |
9694 HInstruction* instr = NULL; | 9693 HInstruction* instr = NULL; |
9695 // Only the stub is allowed to call into the runtime, since otherwise we would | 9694 // Only the stub is allowed to call into the runtime, since otherwise we would |
9696 // inline several instructions (including the two pushes) for every tagged | 9695 // inline several instructions (including the two pushes) for every tagged |
9697 // operation in optimized code, which is more expensive, than a stub call. | 9696 // operation in optimized code, which is more expensive, than a stub call. |
9698 if (graph()->info()->IsStub() && is_non_primitive) { | 9697 if (graph()->info()->IsStub() && is_non_primitive) { |
9699 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); | 9698 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); |
9700 Add<HPushArgument>(left); | 9699 Add<HPushArguments>(zone(), left, right); |
9701 Add<HPushArgument>(right); | |
9702 instr = AddUncasted<HInvokeFunction>(function, 2); | 9700 instr = AddUncasted<HInvokeFunction>(function, 2); |
9703 } else { | 9701 } else { |
9704 switch (op) { | 9702 switch (op) { |
9705 case Token::ADD: | 9703 case Token::ADD: |
9706 instr = AddUncasted<HAdd>(left, right); | 9704 instr = AddUncasted<HAdd>(left, right); |
9707 break; | 9705 break; |
9708 case Token::SUB: | 9706 case Token::SUB: |
9709 instr = AddUncasted<HSub>(left, right); | 9707 instr = AddUncasted<HSub>(left, right); |
9710 break; | 9708 break; |
9711 case Token::MUL: | 9709 case Token::MUL: |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10055 Add<HCheckValue>(right, target); | 10053 Add<HCheckValue>(right, target); |
10056 HInstanceOfKnownGlobal* result = | 10054 HInstanceOfKnownGlobal* result = |
10057 New<HInstanceOfKnownGlobal>(left, target); | 10055 New<HInstanceOfKnownGlobal>(left, target); |
10058 return ast_context()->ReturnInstruction(result, expr->id()); | 10056 return ast_context()->ReturnInstruction(result, expr->id()); |
10059 } | 10057 } |
10060 | 10058 |
10061 // Code below assumes that we don't fall through. | 10059 // Code below assumes that we don't fall through. |
10062 UNREACHABLE(); | 10060 UNREACHABLE(); |
10063 } else if (op == Token::IN) { | 10061 } else if (op == Token::IN) { |
10064 HValue* function = AddLoadJSBuiltin(Builtins::IN); | 10062 HValue* function = AddLoadJSBuiltin(Builtins::IN); |
10065 Add<HPushArgument>(left); | 10063 Add<HPushArguments>(zone(), left, right); |
10066 Add<HPushArgument>(right); | |
10067 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 10064 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
10068 // even though we are certain to pass the correct number of arguments here. | 10065 // even though we are certain to pass the correct number of arguments here. |
10069 HInstruction* result = New<HInvokeFunction>(function, 2); | 10066 HInstruction* result = New<HInvokeFunction>(function, 2); |
10070 return ast_context()->ReturnInstruction(result, expr->id()); | 10067 return ast_context()->ReturnInstruction(result, expr->id()); |
10071 } | 10068 } |
10072 | 10069 |
10073 PushBeforeSimulateBehavior push_behavior = | 10070 PushBeforeSimulateBehavior push_behavior = |
10074 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE | 10071 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE |
10075 : PUSH_BEFORE_SIMULATE; | 10072 : PUSH_BEFORE_SIMULATE; |
10076 HControlInstruction* compare = BuildCompareInstruction( | 10073 HControlInstruction* compare = BuildCompareInstruction( |
(...skipping 1737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11814 if (ShouldProduceTraceOutput()) { | 11811 if (ShouldProduceTraceOutput()) { |
11815 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11812 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11816 } | 11813 } |
11817 | 11814 |
11818 #ifdef DEBUG | 11815 #ifdef DEBUG |
11819 graph_->Verify(false); // No full verify. | 11816 graph_->Verify(false); // No full verify. |
11820 #endif | 11817 #endif |
11821 } | 11818 } |
11822 | 11819 |
11823 } } // namespace v8::internal | 11820 } } // namespace v8::internal |
OLD | NEW |