| 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 "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/allocation-site-scopes.h" | 9 #include "src/allocation-site-scopes.h" |
| 10 #include "src/ast/ast-numbering.h" | 10 #include "src/ast/ast-numbering.h" |
| (...skipping 11662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11673 HValue* left = Pop(); | 11673 HValue* left = Pop(); |
| 11674 Token::Value op = expr->op(); | 11674 Token::Value op = expr->op(); |
| 11675 | 11675 |
| 11676 if (IsLiteralCompareBool(isolate(), left, op, right)) { | 11676 if (IsLiteralCompareBool(isolate(), left, op, right)) { |
| 11677 HCompareObjectEqAndBranch* result = | 11677 HCompareObjectEqAndBranch* result = |
| 11678 New<HCompareObjectEqAndBranch>(left, right); | 11678 New<HCompareObjectEqAndBranch>(left, right); |
| 11679 return ast_context()->ReturnControl(result, expr->id()); | 11679 return ast_context()->ReturnControl(result, expr->id()); |
| 11680 } | 11680 } |
| 11681 | 11681 |
| 11682 if (op == Token::INSTANCEOF) { | 11682 if (op == Token::INSTANCEOF) { |
| 11683 DCHECK(!FLAG_harmony_instanceof); | |
| 11684 // Check to see if the rhs of the instanceof is a known function. | 11683 // Check to see if the rhs of the instanceof is a known function. |
| 11685 if (right->IsConstant() && | 11684 if (right->IsConstant() && |
| 11686 HConstant::cast(right)->handle(isolate())->IsJSFunction()) { | 11685 HConstant::cast(right)->handle(isolate())->IsJSFunction()) { |
| 11687 Handle<JSFunction> constructor = | 11686 Handle<JSFunction> function = |
| 11688 Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate())); | 11687 Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate())); |
| 11689 if (constructor->IsConstructor() && | 11688 // Make sure the prototype of {function} is the %FunctionPrototype%, and |
| 11690 !constructor->map()->has_non_instance_prototype()) { | 11689 // it already has a meaningful initial map (i.e. we constructed at least |
| 11691 JSFunction::EnsureHasInitialMap(constructor); | 11690 // one instance using the constructor {function}). |
| 11692 DCHECK(constructor->has_initial_map()); | 11691 // We can only use the fast case if @@hasInstance was not used so far. |
| 11693 Handle<Map> initial_map(constructor->initial_map(), isolate()); | 11692 if (function->has_initial_map() && |
| 11693 function->map()->prototype() == |
| 11694 function->native_context()->closure() && |
| 11695 !function->map()->has_non_instance_prototype() && |
| 11696 isolate()->IsHasInstanceLookupChainIntact()) { |
| 11697 Handle<Map> initial_map(function->initial_map(), isolate()); |
| 11694 top_info()->dependencies()->AssumeInitialMapCantChange(initial_map); | 11698 top_info()->dependencies()->AssumeInitialMapCantChange(initial_map); |
| 11699 top_info()->dependencies()->AssumePropertyCell( |
| 11700 isolate()->factory()->has_instance_protector()); |
| 11695 HInstruction* prototype = | 11701 HInstruction* prototype = |
| 11696 Add<HConstant>(handle(initial_map->prototype(), isolate())); | 11702 Add<HConstant>(handle(initial_map->prototype(), isolate())); |
| 11697 HHasInPrototypeChainAndBranch* result = | 11703 HHasInPrototypeChainAndBranch* result = |
| 11698 New<HHasInPrototypeChainAndBranch>(left, prototype); | 11704 New<HHasInPrototypeChainAndBranch>(left, prototype); |
| 11699 return ast_context()->ReturnControl(result, expr->id()); | 11705 return ast_context()->ReturnControl(result, expr->id()); |
| 11700 } | 11706 } |
| 11701 } | 11707 } |
| 11702 | 11708 |
| 11703 HInstanceOf* result = New<HInstanceOf>(left, right); | 11709 Callable callable = CodeFactory::InstanceOf(isolate()); |
| 11710 HValue* stub = Add<HConstant>(callable.code()); |
| 11711 HValue* values[] = {context(), left, right}; |
| 11712 HCallWithDescriptor* result = New<HCallWithDescriptor>( |
| 11713 stub, 0, callable.descriptor(), ArrayVector(values)); |
| 11714 result->set_type(HType::Boolean()); |
| 11704 return ast_context()->ReturnInstruction(result, expr->id()); | 11715 return ast_context()->ReturnInstruction(result, expr->id()); |
| 11705 | 11716 |
| 11706 } else if (op == Token::IN) { | 11717 } else if (op == Token::IN) { |
| 11707 Callable callable = CodeFactory::HasProperty(isolate()); | 11718 Callable callable = CodeFactory::HasProperty(isolate()); |
| 11708 HValue* stub = Add<HConstant>(callable.code()); | 11719 HValue* stub = Add<HConstant>(callable.code()); |
| 11709 HValue* values[] = {context(), left, right}; | 11720 HValue* values[] = {context(), left, right}; |
| 11710 HInstruction* result = | 11721 HInstruction* result = |
| 11711 New<HCallWithDescriptor>(stub, 0, callable.descriptor(), | 11722 New<HCallWithDescriptor>(stub, 0, callable.descriptor(), |
| 11712 Vector<HValue*>(values, arraysize(values))); | 11723 Vector<HValue*>(values, arraysize(values))); |
| 11713 return ast_context()->ReturnInstruction(result, expr->id()); | 11724 return ast_context()->ReturnInstruction(result, expr->id()); |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12794 HValue* number = Pop(); | 12805 HValue* number = Pop(); |
| 12795 HValue* result = BuildNumberToString(number, Type::Any()); | 12806 HValue* result = BuildNumberToString(number, Type::Any()); |
| 12796 return ast_context()->ReturnValue(result); | 12807 return ast_context()->ReturnValue(result); |
| 12797 } | 12808 } |
| 12798 | 12809 |
| 12799 | 12810 |
| 12800 // Fast support for calls. | 12811 // Fast support for calls. |
| 12801 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) { | 12812 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) { |
| 12802 DCHECK_LE(2, call->arguments()->length()); | 12813 DCHECK_LE(2, call->arguments()->length()); |
| 12803 CHECK_ALIVE(VisitExpressions(call->arguments())); | 12814 CHECK_ALIVE(VisitExpressions(call->arguments())); |
| 12804 | |
| 12805 // Try and customize ES6 instanceof here. | |
| 12806 // We should at least have the constructor on the expression stack. | |
| 12807 if (FLAG_harmony_instanceof && FLAG_harmony_instanceof_opt && | |
| 12808 call->arguments()->length() == 3) { | |
| 12809 HValue* target = environment()->ExpressionStackAt(2); | |
| 12810 if (target->IsConstant()) { | |
| 12811 HConstant* constant_function = HConstant::cast(target); | |
| 12812 if (constant_function->handle(isolate())->IsJSFunction()) { | |
| 12813 Handle<JSFunction> func = | |
| 12814 Handle<JSFunction>::cast(constant_function->handle(isolate())); | |
| 12815 if (*func == isolate()->native_context()->ordinary_has_instance()) { | |
| 12816 // Look at the function, which will be argument 1. | |
| 12817 HValue* right = environment()->ExpressionStackAt(1); | |
| 12818 if (right->IsConstant() && | |
| 12819 HConstant::cast(right)->handle(isolate())->IsJSFunction()) { | |
| 12820 Handle<JSFunction> constructor = Handle<JSFunction>::cast( | |
| 12821 HConstant::cast(right)->handle(isolate())); | |
| 12822 if (constructor->IsConstructor() && | |
| 12823 !constructor->map()->has_non_instance_prototype()) { | |
| 12824 JSFunction::EnsureHasInitialMap(constructor); | |
| 12825 DCHECK(constructor->has_initial_map()); | |
| 12826 Handle<Map> initial_map(constructor->initial_map(), isolate()); | |
| 12827 top_info()->dependencies()->AssumeInitialMapCantChange( | |
| 12828 initial_map); | |
| 12829 HInstruction* prototype = | |
| 12830 Add<HConstant>(handle(initial_map->prototype(), isolate())); | |
| 12831 HValue* left = environment()->ExpressionStackAt(0); | |
| 12832 HHasInPrototypeChainAndBranch* result = | |
| 12833 New<HHasInPrototypeChainAndBranch>(left, prototype); | |
| 12834 Drop(3); | |
| 12835 return ast_context()->ReturnControl(result, call->id()); | |
| 12836 } | |
| 12837 } | |
| 12838 } | |
| 12839 } | |
| 12840 } | |
| 12841 } | |
| 12842 | |
| 12843 CallTrampolineDescriptor descriptor(isolate()); | 12815 CallTrampolineDescriptor descriptor(isolate()); |
| 12844 PushArgumentsFromEnvironment(call->arguments()->length() - 1); | 12816 PushArgumentsFromEnvironment(call->arguments()->length() - 1); |
| 12845 HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call()); | 12817 HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call()); |
| 12846 HValue* target = Pop(); | 12818 HValue* target = Pop(); |
| 12847 HValue* values[] = {context(), target, | 12819 HValue* values[] = {context(), target, |
| 12848 Add<HConstant>(call->arguments()->length() - 2)}; | 12820 Add<HConstant>(call->arguments()->length() - 2)}; |
| 12849 HInstruction* result = | 12821 HInstruction* result = |
| 12850 New<HCallWithDescriptor>(trampoline, call->arguments()->length() - 1, | 12822 New<HCallWithDescriptor>(trampoline, call->arguments()->length() - 1, |
| 12851 descriptor, ArrayVector(values)); | 12823 descriptor, ArrayVector(values)); |
| 12852 return ast_context()->ReturnInstruction(result, call->id()); | 12824 return ast_context()->ReturnInstruction(result, call->id()); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13073 | 13045 |
| 13074 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) { | 13046 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) { |
| 13075 DCHECK(call->arguments()->length() == 0); | 13047 DCHECK(call->arguments()->length() == 0); |
| 13076 HValue* ref = | 13048 HValue* ref = |
| 13077 Add<HConstant>(ExternalReference::debug_is_active_address(isolate())); | 13049 Add<HConstant>(ExternalReference::debug_is_active_address(isolate())); |
| 13078 HValue* value = | 13050 HValue* value = |
| 13079 Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8()); | 13051 Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8()); |
| 13080 return ast_context()->ReturnValue(value); | 13052 return ast_context()->ReturnValue(value); |
| 13081 } | 13053 } |
| 13082 | 13054 |
| 13083 void HOptimizedGraphBuilder::GenerateGetOrdinaryHasInstance(CallRuntime* call) { | |
| 13084 DCHECK(call->arguments()->length() == 0); | |
| 13085 // ordinary_has_instance is immutable so we can treat it as a constant. | |
| 13086 HValue* value = Add<HConstant>(isolate()->ordinary_has_instance()); | |
| 13087 return ast_context()->ReturnValue(value); | |
| 13088 } | |
| 13089 | |
| 13090 #undef CHECK_BAILOUT | 13055 #undef CHECK_BAILOUT |
| 13091 #undef CHECK_ALIVE | 13056 #undef CHECK_ALIVE |
| 13092 | 13057 |
| 13093 | 13058 |
| 13094 HEnvironment::HEnvironment(HEnvironment* outer, | 13059 HEnvironment::HEnvironment(HEnvironment* outer, |
| 13095 Scope* scope, | 13060 Scope* scope, |
| 13096 Handle<JSFunction> closure, | 13061 Handle<JSFunction> closure, |
| 13097 Zone* zone) | 13062 Zone* zone) |
| 13098 : closure_(closure), | 13063 : closure_(closure), |
| 13099 values_(0, zone), | 13064 values_(0, zone), |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13743 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13708 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13744 } | 13709 } |
| 13745 | 13710 |
| 13746 #ifdef DEBUG | 13711 #ifdef DEBUG |
| 13747 graph_->Verify(false); // No full verify. | 13712 graph_->Verify(false); // No full verify. |
| 13748 #endif | 13713 #endif |
| 13749 } | 13714 } |
| 13750 | 13715 |
| 13751 } // namespace internal | 13716 } // namespace internal |
| 13752 } // namespace v8 | 13717 } // namespace v8 |
| OLD | NEW |