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 |