Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: src/hydrogen.cc

Issue 347573002: Revert "Optimize Function.prototype.call" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/hydrogen.h" 5 #include "src/hydrogen.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "src/v8.h" 9 #include "src/v8.h"
10 #include "src/allocation-site-scopes.h" 10 #include "src/allocation-site-scopes.h"
(...skipping 7905 matching lines...) Expand 10 before | Expand all | Expand 10 after
7916 if (TryInlineApiSetter(setter, receiver_map, id)) return true; 7916 if (TryInlineApiSetter(setter, receiver_map, id)) return true;
7917 return TryInline(setter, 7917 return TryInline(setter,
7918 1, 7918 1,
7919 implicit_return_value, 7919 implicit_return_value,
7920 id, assignment_id, 7920 id, assignment_id,
7921 SETTER_CALL_RETURN, 7921 SETTER_CALL_RETURN,
7922 source_position()); 7922 source_position());
7923 } 7923 }
7924 7924
7925 7925
7926 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function, 7926 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
7927 Call* expr, 7927 Call* expr,
7928 int arguments_count) { 7928 int arguments_count) {
7929 return TryInline(function, 7929 return TryInline(function,
7930 arguments_count, 7930 arguments_count,
7931 NULL, 7931 NULL,
7932 expr->id(), 7932 expr->id(),
7933 expr->ReturnId(), 7933 expr->ReturnId(),
7934 NORMAL_RETURN, 7934 NORMAL_RETURN,
7935 ScriptPositionToSourcePosition(expr->position())); 7935 ScriptPositionToSourcePosition(expr->position()));
7936 } 7936 }
7937 7937
7938 7938
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
7970 default: 7970 default:
7971 // Not supported for inlining yet. 7971 // Not supported for inlining yet.
7972 break; 7972 break;
7973 } 7973 }
7974 return false; 7974 return false;
7975 } 7975 }
7976 7976
7977 7977
7978 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( 7978 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
7979 Call* expr, 7979 Call* expr,
7980 Handle<JSFunction> function, 7980 HValue* receiver,
7981 Handle<Map> receiver_map, 7981 Handle<Map> receiver_map) {
7982 int args_count_no_receiver) {
7983 if (!function->shared()->HasBuiltinFunctionId()) return false;
7984 BuiltinFunctionId id = function->shared()->builtin_function_id();
7985 int argument_count = args_count_no_receiver + 1; // Plus receiver.
7986
7987 if (receiver_map.is_null()) {
7988 HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
7989 if (receiver->IsConstant() &&
7990 HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
7991 receiver_map = handle(Handle<HeapObject>::cast(
7992 HConstant::cast(receiver)->handle(isolate()))->map());
7993 }
7994 }
7995 // Try to inline calls like Math.* as operations in the calling function. 7982 // Try to inline calls like Math.* as operations in the calling function.
7983 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
7984 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7985 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7996 switch (id) { 7986 switch (id) {
7997 case kStringCharCodeAt: 7987 case kStringCharCodeAt:
7998 case kStringCharAt: 7988 case kStringCharAt:
7999 if (argument_count == 2) { 7989 if (argument_count == 2) {
8000 HValue* index = Pop(); 7990 HValue* index = Pop();
8001 HValue* string = Pop(); 7991 HValue* string = Pop();
8002 Drop(1); // Function. 7992 Drop(1); // Function.
8003 HInstruction* char_code = 7993 HInstruction* char_code =
8004 BuildStringCharCodeAt(string, index); 7994 BuildStringCharCodeAt(string, index);
8005 if (id == kStringCharCodeAt) { 7995 if (id == kStringCharCodeAt) {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
8093 } 8083 }
8094 break; 8084 break;
8095 case kArrayPop: { 8085 case kArrayPop: {
8096 if (receiver_map.is_null()) return false; 8086 if (receiver_map.is_null()) return false;
8097 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; 8087 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8098 ElementsKind elements_kind = receiver_map->elements_kind(); 8088 ElementsKind elements_kind = receiver_map->elements_kind();
8099 if (!IsFastElementsKind(elements_kind)) return false; 8089 if (!IsFastElementsKind(elements_kind)) return false;
8100 if (receiver_map->is_observed()) return false; 8090 if (receiver_map->is_observed()) return false;
8101 ASSERT(receiver_map->is_extensible()); 8091 ASSERT(receiver_map->is_extensible());
8102 8092
8103 Drop(args_count_no_receiver); 8093 Drop(expr->arguments()->length());
8104 HValue* result; 8094 HValue* result;
8105 HValue* reduced_length; 8095 HValue* reduced_length;
8106 HValue* receiver = Pop(); 8096 HValue* receiver = Pop();
8107 8097
8108 HValue* checked_object = AddCheckMap(receiver, receiver_map); 8098 HValue* checked_object = AddCheckMap(receiver, receiver_map);
8109 HValue* length = Add<HLoadNamedField>( 8099 HValue* length = Add<HLoadNamedField>(
8110 checked_object, static_cast<HValue*>(NULL), 8100 checked_object, static_cast<HValue*>(NULL),
8111 HObjectAccess::ForArrayLength(elements_kind)); 8101 HObjectAccess::ForArrayLength(elements_kind));
8112 8102
8113 Drop(1); // Function. 8103 Drop(1); // Function.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
8169 // inlined version can't be used. 8159 // inlined version can't be used.
8170 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; 8160 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8171 // If there currently can be no elements accessors on the prototype chain, 8161 // If there currently can be no elements accessors on the prototype chain,
8172 // it doesn't mean that there won't be any later. Install a full prototype 8162 // it doesn't mean that there won't be any later. Install a full prototype
8173 // chain check to trap element accessors being installed on the prototype 8163 // chain check to trap element accessors being installed on the prototype
8174 // chain, which would cause elements to go to dictionary mode and result 8164 // chain, which would cause elements to go to dictionary mode and result
8175 // in a map change. 8165 // in a map change.
8176 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 8166 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
8177 BuildCheckPrototypeMaps(prototype, Handle<JSObject>()); 8167 BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
8178 8168
8179 const int argc = args_count_no_receiver; 8169 const int argc = expr->arguments()->length();
8180 if (argc != 1) return false; 8170 if (argc != 1) return false;
8181 8171
8182 HValue* value_to_push = Pop(); 8172 HValue* value_to_push = Pop();
8183 HValue* array = Pop(); 8173 HValue* array = Pop();
8184 Drop(1); // Drop function. 8174 Drop(1); // Drop function.
8185 8175
8186 HInstruction* new_size = NULL; 8176 HInstruction* new_size = NULL;
8187 HValue* length = NULL; 8177 HValue* length = NULL;
8188 8178
8189 { 8179 {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
8226 // chain check to trap element accessors being installed on the prototype 8216 // chain check to trap element accessors being installed on the prototype
8227 // chain, which would cause elements to go to dictionary mode and result 8217 // chain, which would cause elements to go to dictionary mode and result
8228 // in a map change. 8218 // in a map change.
8229 BuildCheckPrototypeMaps( 8219 BuildCheckPrototypeMaps(
8230 handle(JSObject::cast(receiver_map->prototype()), isolate()), 8220 handle(JSObject::cast(receiver_map->prototype()), isolate()),
8231 Handle<JSObject>::null()); 8221 Handle<JSObject>::null());
8232 8222
8233 // Threshold for fast inlined Array.shift(). 8223 // Threshold for fast inlined Array.shift().
8234 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16)); 8224 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
8235 8225
8236 Drop(args_count_no_receiver); 8226 Drop(expr->arguments()->length());
8237 HValue* receiver = Pop(); 8227 HValue* receiver = Pop();
8238 HValue* function = Pop(); 8228 HValue* function = Pop();
8239 HValue* result; 8229 HValue* result;
8240 8230
8241 { 8231 {
8242 NoObservableSideEffectsScope scope(this); 8232 NoObservableSideEffectsScope scope(this);
8243 8233
8244 HValue* length = Add<HLoadNamedField>( 8234 HValue* length = Add<HLoadNamedField>(
8245 receiver, static_cast<HValue*>(NULL), 8235 receiver, static_cast<HValue*>(NULL),
8246 HObjectAccess::ForArrayLength(kind)); 8236 HObjectAccess::ForArrayLength(kind));
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
8537 HInstruction* call = New<HCallWithDescriptor>( 8527 HInstruction* call = New<HCallWithDescriptor>(
8538 code_value, argc + 1, descriptor, 8528 code_value, argc + 1, descriptor,
8539 Vector<HValue*>(op_vals, descriptor->environment_length())); 8529 Vector<HValue*>(op_vals, descriptor->environment_length()));
8540 8530
8541 if (drop_extra) Drop(1); // Drop function. 8531 if (drop_extra) Drop(1); // Drop function.
8542 ast_context()->ReturnInstruction(call, ast_id); 8532 ast_context()->ReturnInstruction(call, ast_id);
8543 return true; 8533 return true;
8544 } 8534 }
8545 8535
8546 8536
8547 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, 8537 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
8548 HValue* function,
8549 int arguments_count) {
8550 Handle<JSFunction> known_function;
8551 int args_count_no_receiver = arguments_count - 1;
8552 if (function->IsConstant() &&
8553 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8554 known_function = Handle<JSFunction>::cast(
8555 HConstant::cast(function)->handle(isolate()));
8556 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
8557 return;
8558 }
8559
8560 Handle<Map> map;
8561 if (TryInlineBuiltinMethodCall(expr, known_function, map,
8562 args_count_no_receiver)) {
8563 if (FLAG_trace_inlining) {
8564 PrintF("Inlining builtin ");
8565 known_function->ShortPrint();
8566 PrintF("\n");
8567 }
8568 return;
8569 }
8570 }
8571
8572 PushArgumentsFromEnvironment(arguments_count);
8573 HInvokeFunction* call = New<HInvokeFunction>(
8574 function, known_function, arguments_count);
8575 Drop(1); // Function
8576 ast_context()->ReturnInstruction(call, expr->id());
8577 }
8578
8579
8580 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
8581 ASSERT(expr->expression()->IsProperty()); 8538 ASSERT(expr->expression()->IsProperty());
8582 8539
8583 if (!expr->IsMonomorphic()) { 8540 if (!expr->IsMonomorphic()) {
8584 return false; 8541 return false;
8585 } 8542 }
8586
8587 Handle<Map> function_map = expr->GetReceiverTypes()->first(); 8543 Handle<Map> function_map = expr->GetReceiverTypes()->first();
8588 if (function_map->instance_type() != JS_FUNCTION_TYPE || 8544 if (function_map->instance_type() != JS_FUNCTION_TYPE ||
8589 !expr->target()->shared()->HasBuiltinFunctionId()) { 8545 !expr->target()->shared()->HasBuiltinFunctionId() ||
8546 expr->target()->shared()->builtin_function_id() != kFunctionApply) {
8590 return false; 8547 return false;
8591 } 8548 }
8592 8549
8593 switch (expr->target()->shared()->builtin_function_id()) { 8550 if (current_info()->scope()->arguments() == NULL) return false;
8594 case kFunctionCall: {
8595 BuildFunctionCall(expr);
8596 return true;
8597 }
8598 case kFunctionApply: {
8599 // For .apply, only the pattern f.apply(receiver, arguments)
8600 // is supported.
8601 if (current_info()->scope()->arguments() == NULL) return false;
8602 8551
8603 ZoneList<Expression*>* args = expr->arguments(); 8552 ZoneList<Expression*>* args = expr->arguments();
8604 if (args->length() != 2) return false; 8553 if (args->length() != 2) return false;
8605 8554
8606 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 8555 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
8607 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 8556 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
8608 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); 8557 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
8609 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 8558 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
8610 BuildFunctionApply(expr);
8611 return true;
8612 }
8613 default: {
8614 return false;
8615 }
8616 }
8617 UNREACHABLE();
8618 }
8619 8559
8620 8560 // Found pattern f.apply(receiver, arguments).
8621 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) { 8561 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
8622 ZoneList<Expression*>* args = expr->arguments();
8623 CHECK_ALIVE(VisitForValue(args->at(0)));
8624 HValue* receiver = Pop(); // receiver 8562 HValue* receiver = Pop(); // receiver
8625 HValue* function = Pop(); // f 8563 HValue* function = Pop(); // f
8626 Drop(1); // apply 8564 Drop(1); // apply
8627 8565
8628 if (function_state()->outer() == NULL) { 8566 if (function_state()->outer() == NULL) {
8629 HInstruction* elements = Add<HArgumentsElements>(false); 8567 HInstruction* elements = Add<HArgumentsElements>(false);
8630 HInstruction* length = Add<HArgumentsLength>(elements); 8568 HInstruction* length = Add<HArgumentsLength>(elements);
8631 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); 8569 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function);
8632 HInstruction* result = New<HApplyArguments>(function, 8570 HInstruction* result = New<HApplyArguments>(function,
8633 wrapped_receiver, 8571 wrapped_receiver,
8634 length, 8572 length,
8635 elements); 8573 elements);
8636 ast_context()->ReturnInstruction(result, expr->id()); 8574 ast_context()->ReturnInstruction(result, expr->id());
8575 return true;
8637 } else { 8576 } else {
8638 // We are inside inlined function and we know exactly what is inside 8577 // We are inside inlined function and we know exactly what is inside
8639 // arguments object. But we need to be able to materialize at deopt. 8578 // arguments object. But we need to be able to materialize at deopt.
8640 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), 8579 ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
8641 function_state()->entry()->arguments_object()->arguments_count()); 8580 function_state()->entry()->arguments_object()->arguments_count());
8642 HArgumentsObject* args = function_state()->entry()->arguments_object(); 8581 HArgumentsObject* args = function_state()->entry()->arguments_object();
8643 const ZoneList<HValue*>* arguments_values = args->arguments_values(); 8582 const ZoneList<HValue*>* arguments_values = args->arguments_values();
8644 int arguments_count = arguments_values->length(); 8583 int arguments_count = arguments_values->length();
8645 Push(function); 8584 Push(function);
8646 Push(BuildWrapReceiver(receiver, function)); 8585 Push(BuildWrapReceiver(receiver, function));
8647 for (int i = 1; i < arguments_count; i++) { 8586 for (int i = 1; i < arguments_count; i++) {
8648 Push(arguments_values->at(i)); 8587 Push(arguments_values->at(i));
8649 } 8588 }
8650 HandleIndirectCall(expr, function, arguments_count); 8589
8590 Handle<JSFunction> known_function;
8591 if (function->IsConstant() &&
8592 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8593 known_function = Handle<JSFunction>::cast(
8594 HConstant::cast(function)->handle(isolate()));
8595 int args_count = arguments_count - 1; // Excluding receiver.
8596 if (TryInlineApply(known_function, expr, args_count)) return true;
8597 }
8598
8599 PushArgumentsFromEnvironment(arguments_count);
8600 HInvokeFunction* call = New<HInvokeFunction>(
8601 function, known_function, arguments_count);
8602 Drop(1); // Function.
8603 ast_context()->ReturnInstruction(call, expr->id());
8604 return true;
8651 } 8605 }
8652 } 8606 }
8653 8607
8654 8608
8655 // f.call(...)
8656 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
8657 HValue* function = Pop(); // f
8658 HValue* receiver;
8659 ZoneList<Expression*>* args = expr->arguments();
8660 int args_length = args->length();
8661 Drop(1); // call
8662
8663 if (args_length == 0) {
8664 receiver = graph()->GetConstantUndefined();
8665 args_length = 1;
8666 } else {
8667 CHECK_ALIVE(VisitForValue(args->at(0)));
8668 receiver = Pop();
8669 }
8670 receiver = BuildWrapReceiver(receiver, function);
8671
8672 Push(function);
8673 Push(receiver);
8674 for (int i = 1; i < args_length; i++) {
8675 CHECK_ALIVE(VisitForValue(args->at(i)));
8676 }
8677 HandleIndirectCall(expr, function, args_length);
8678 }
8679
8680
8681 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, 8609 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
8682 Handle<JSFunction> target) { 8610 Handle<JSFunction> target) {
8683 SharedFunctionInfo* shared = target->shared(); 8611 SharedFunctionInfo* shared = target->shared();
8684 if (shared->strict_mode() == SLOPPY && !shared->native()) { 8612 if (shared->strict_mode() == SLOPPY && !shared->native()) {
8685 // Cannot embed a direct reference to the global proxy 8613 // Cannot embed a direct reference to the global proxy
8686 // as is it dropped on deserialization. 8614 // as is it dropped on deserialization.
8687 CHECK(!isolate()->serializer_enabled()); 8615 CHECK(!isolate()->serializer_enabled());
8688 Handle<JSObject> global_receiver( 8616 Handle<JSObject> global_receiver(
8689 target->context()->global_object()->global_receiver()); 8617 target->context()->global_object()->global_receiver());
8690 return Add<HConstant>(global_receiver); 8618 return Add<HConstant>(global_receiver);
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
8932 environment()->SetExpressionStackAt(0, function); 8860 environment()->SetExpressionStackAt(0, function);
8933 8861
8934 Push(receiver); 8862 Push(receiver);
8935 8863
8936 if (function->IsConstant() && 8864 if (function->IsConstant() &&
8937 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { 8865 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8938 Handle<JSFunction> known_function = Handle<JSFunction>::cast( 8866 Handle<JSFunction> known_function = Handle<JSFunction>::cast(
8939 HConstant::cast(function)->handle(isolate())); 8867 HConstant::cast(function)->handle(isolate()));
8940 expr->set_target(known_function); 8868 expr->set_target(known_function);
8941 8869
8942 if (TryIndirectCall(expr)) return; 8870 if (TryCallApply(expr)) return;
8943 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8871 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8944 8872
8945 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); 8873 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
8946 if (TryInlineBuiltinMethodCall(expr, known_function, map, 8874 if (TryInlineBuiltinMethodCall(expr, receiver, map)) {
8947 expr->arguments()->length())) {
8948 if (FLAG_trace_inlining) { 8875 if (FLAG_trace_inlining) {
8949 PrintF("Inlining builtin "); 8876 PrintF("Inlining builtin ");
8950 known_function->ShortPrint(); 8877 known_function->ShortPrint();
8951 PrintF("\n"); 8878 PrintF("\n");
8952 } 8879 }
8953 return; 8880 return;
8954 } 8881 }
8955 if (TryInlineApiMethodCall(expr, receiver, types)) return; 8882 if (TryInlineApiMethodCall(expr, receiver, types)) return;
8956 8883
8957 // Wrap the receiver if necessary. 8884 // Wrap the receiver if necessary.
(...skipping 3459 matching lines...) Expand 10 before | Expand all | Expand 10 after
12417 if (ShouldProduceTraceOutput()) { 12344 if (ShouldProduceTraceOutput()) {
12418 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 12345 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
12419 } 12346 }
12420 12347
12421 #ifdef DEBUG 12348 #ifdef DEBUG
12422 graph_->Verify(false); // No full verify. 12349 graph_->Verify(false); // No full verify.
12423 #endif 12350 #endif
12424 } 12351 }
12425 12352
12426 } } // namespace v8::internal 12353 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698