| 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 |