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

Side by Side Diff: src/hydrogen.cc

Issue 350913002: Optimize Function.prototype.call (Closed) Base URL: https://github.com/v8/v8.git@master
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
« 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 10
(...skipping 7909 matching lines...) Expand 10 before | Expand all | Expand 10 after
7920 if (TryInlineApiSetter(setter, receiver_map, id)) return true; 7920 if (TryInlineApiSetter(setter, receiver_map, id)) return true;
7921 return TryInline(setter, 7921 return TryInline(setter,
7922 1, 7922 1,
7923 implicit_return_value, 7923 implicit_return_value,
7924 id, assignment_id, 7924 id, assignment_id,
7925 SETTER_CALL_RETURN, 7925 SETTER_CALL_RETURN,
7926 source_position()); 7926 source_position());
7927 } 7927 }
7928 7928
7929 7929
7930 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, 7930 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
7931 Call* expr, 7931 Call* expr,
7932 int arguments_count) { 7932 int arguments_count) {
7933 return TryInline(function, 7933 return TryInline(function,
7934 arguments_count, 7934 arguments_count,
7935 NULL, 7935 NULL,
7936 expr->id(), 7936 expr->id(),
7937 expr->ReturnId(), 7937 expr->ReturnId(),
7938 NORMAL_RETURN, 7938 NORMAL_RETURN,
7939 ScriptPositionToSourcePosition(expr->position())); 7939 ScriptPositionToSourcePosition(expr->position()));
7940 } 7940 }
7941 7941
7942 7942
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
7974 default: 7974 default:
7975 // Not supported for inlining yet. 7975 // Not supported for inlining yet.
7976 break; 7976 break;
7977 } 7977 }
7978 return false; 7978 return false;
7979 } 7979 }
7980 7980
7981 7981
7982 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( 7982 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
7983 Call* expr, 7983 Call* expr,
7984 HValue* receiver, 7984 Handle<JSFunction> function,
7985 Handle<Map> receiver_map) { 7985 Handle<Map> receiver_map,
7986 int args_count_no_receiver,
7987 int drop_extra) {
7988 if (!function->shared()->HasBuiltinFunctionId()) return false;
7989 BuiltinFunctionId id = function->shared()->builtin_function_id();
7990 int argument_count = args_count_no_receiver + 1; // Plus receiver.
7991
7992 if (receiver_map.is_null()) {
7993 HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
7994 if (receiver->IsConstant() &&
7995 HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
7996 receiver_map = handle(Handle<HeapObject>::cast(
7997 HConstant::cast(receiver)->handle(isolate()))->map());
7998 }
7999 }
7986 // Try to inline calls like Math.* as operations in the calling function. 8000 // Try to inline calls like Math.* as operations in the calling function.
7987 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
7988 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7989 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7990 switch (id) { 8001 switch (id) {
7991 case kStringCharCodeAt: 8002 case kStringCharCodeAt:
7992 case kStringCharAt: 8003 case kStringCharAt:
7993 if (argument_count == 2) { 8004 if (argument_count == 2) {
7994 HValue* index = Pop(); 8005 HValue* index = Pop();
7995 HValue* string = Pop(); 8006 HValue* string = Pop();
7996 Drop(1); // Function. 8007 Drop(1 + drop_extra); // Function + extra.
7997 HInstruction* char_code = 8008 HInstruction* char_code =
7998 BuildStringCharCodeAt(string, index); 8009 BuildStringCharCodeAt(string, index);
7999 if (id == kStringCharCodeAt) { 8010 if (id == kStringCharCodeAt) {
8000 ast_context()->ReturnInstruction(char_code, expr->id()); 8011 ast_context()->ReturnInstruction(char_code, expr->id());
8001 return true; 8012 return true;
8002 } 8013 }
8003 AddInstruction(char_code); 8014 AddInstruction(char_code);
8004 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); 8015 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
8005 ast_context()->ReturnInstruction(result, expr->id()); 8016 ast_context()->ReturnInstruction(result, expr->id());
8006 return true; 8017 return true;
8007 } 8018 }
8008 break; 8019 break;
8009 case kStringFromCharCode: 8020 case kStringFromCharCode:
8010 if (argument_count == 2) { 8021 if (argument_count == 2) {
8011 HValue* argument = Pop(); 8022 HValue* argument = Pop();
8012 Drop(2); // Receiver and function. 8023 Drop(2 + drop_extra); // Receiver and function + extra.
8013 HInstruction* result = NewUncasted<HStringCharFromCode>(argument); 8024 HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
8014 ast_context()->ReturnInstruction(result, expr->id()); 8025 ast_context()->ReturnInstruction(result, expr->id());
8015 return true; 8026 return true;
8016 } 8027 }
8017 break; 8028 break;
8018 case kMathExp: 8029 case kMathExp:
8019 if (!FLAG_fast_math) break; 8030 if (!FLAG_fast_math) break;
8020 // Fall through if FLAG_fast_math. 8031 // Fall through if FLAG_fast_math.
8021 case kMathRound: 8032 case kMathRound:
8022 case kMathFloor: 8033 case kMathFloor:
8023 case kMathAbs: 8034 case kMathAbs:
8024 case kMathSqrt: 8035 case kMathSqrt:
8025 case kMathLog: 8036 case kMathLog:
8026 case kMathClz32: 8037 case kMathClz32:
8027 if (argument_count == 2) { 8038 if (argument_count == 2) {
8028 HValue* argument = Pop(); 8039 HValue* argument = Pop();
8029 Drop(2); // Receiver and function. 8040 Drop(2 + drop_extra); // Receiver and function + extra.
8030 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 8041 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8031 ast_context()->ReturnInstruction(op, expr->id()); 8042 ast_context()->ReturnInstruction(op, expr->id());
8032 return true; 8043 return true;
8033 } 8044 }
8034 break; 8045 break;
8035 case kMathPow: 8046 case kMathPow:
8036 if (argument_count == 3) { 8047 if (argument_count == 3) {
8037 HValue* right = Pop(); 8048 HValue* right = Pop();
8038 HValue* left = Pop(); 8049 HValue* left = Pop();
8039 Drop(2); // Receiver and function. 8050 Drop(2 + drop_extra); // Receiver and function + extra.
8040 HInstruction* result = NULL; 8051 HInstruction* result = NULL;
8041 // Use sqrt() if exponent is 0.5 or -0.5. 8052 // Use sqrt() if exponent is 0.5 or -0.5.
8042 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 8053 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
8043 double exponent = HConstant::cast(right)->DoubleValue(); 8054 double exponent = HConstant::cast(right)->DoubleValue();
8044 if (exponent == 0.5) { 8055 if (exponent == 0.5) {
8045 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf); 8056 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
8046 } else if (exponent == -0.5) { 8057 } else if (exponent == -0.5) {
8047 HValue* one = graph()->GetConstant1(); 8058 HValue* one = graph()->GetConstant1();
8048 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>( 8059 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
8049 left, kMathPowHalf); 8060 left, kMathPowHalf);
(...skipping 11 matching lines...) Expand all
8061 } 8072 }
8062 ast_context()->ReturnInstruction(result, expr->id()); 8073 ast_context()->ReturnInstruction(result, expr->id());
8063 return true; 8074 return true;
8064 } 8075 }
8065 break; 8076 break;
8066 case kMathMax: 8077 case kMathMax:
8067 case kMathMin: 8078 case kMathMin:
8068 if (argument_count == 3) { 8079 if (argument_count == 3) {
8069 HValue* right = Pop(); 8080 HValue* right = Pop();
8070 HValue* left = Pop(); 8081 HValue* left = Pop();
8071 Drop(2); // Receiver and function. 8082 Drop(2 + drop_extra); // Receiver and function + extra.
8072 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin 8083 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
8073 : HMathMinMax::kMathMax; 8084 : HMathMinMax::kMathMax;
8074 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); 8085 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
8075 ast_context()->ReturnInstruction(result, expr->id()); 8086 ast_context()->ReturnInstruction(result, expr->id());
8076 return true; 8087 return true;
8077 } 8088 }
8078 break; 8089 break;
8079 case kMathImul: 8090 case kMathImul:
8080 if (argument_count == 3) { 8091 if (argument_count == 3) {
8081 HValue* right = Pop(); 8092 HValue* right = Pop();
8082 HValue* left = Pop(); 8093 HValue* left = Pop();
8083 Drop(2); // Receiver and function. 8094 Drop(2 + drop_extra); // Receiver and function + extra.
8084 HInstruction* result = HMul::NewImul(zone(), context(), left, right); 8095 HInstruction* result = HMul::NewImul(zone(), context(), left, right);
8085 ast_context()->ReturnInstruction(result, expr->id()); 8096 ast_context()->ReturnInstruction(result, expr->id());
8086 return true; 8097 return true;
8087 } 8098 }
8088 break; 8099 break;
8089 case kArrayPop: { 8100 case kArrayPop: {
8090 if (receiver_map.is_null()) return false; 8101 if (receiver_map.is_null()) return false;
8091 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; 8102 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8092 ElementsKind elements_kind = receiver_map->elements_kind(); 8103 ElementsKind elements_kind = receiver_map->elements_kind();
8093 if (!IsFastElementsKind(elements_kind)) return false; 8104 if (!IsFastElementsKind(elements_kind)) return false;
8094 if (receiver_map->is_observed()) return false; 8105 if (receiver_map->is_observed()) return false;
8095 ASSERT(receiver_map->is_extensible()); 8106 ASSERT(receiver_map->is_extensible());
8096 8107
8097 Drop(expr->arguments()->length()); 8108 Drop(args_count_no_receiver);
8098 HValue* result; 8109 HValue* result;
8099 HValue* reduced_length; 8110 HValue* reduced_length;
8100 HValue* receiver = Pop(); 8111 HValue* receiver = Pop();
8101 8112
8102 HValue* checked_object = AddCheckMap(receiver, receiver_map); 8113 HValue* checked_object = AddCheckMap(receiver, receiver_map);
8103 HValue* length = Add<HLoadNamedField>( 8114 HValue* length = Add<HLoadNamedField>(
8104 checked_object, static_cast<HValue*>(NULL), 8115 checked_object, static_cast<HValue*>(NULL),
8105 HObjectAccess::ForArrayLength(elements_kind)); 8116 HObjectAccess::ForArrayLength(elements_kind));
8106 8117
8107 Drop(1); // Function. 8118 Drop(1 + drop_extra); // Function + extra.
8108 8119
8109 { NoObservableSideEffectsScope scope(this); 8120 { NoObservableSideEffectsScope scope(this);
8110 IfBuilder length_checker(this); 8121 IfBuilder length_checker(this);
8111 8122
8112 HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>( 8123 HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
8113 length, graph()->GetConstant0(), Token::EQ); 8124 length, graph()->GetConstant0(), Token::EQ);
8114 length_checker.Then(); 8125 length_checker.Then();
8115 8126
8116 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined()); 8127 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8117 8128
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8163 // inlined version can't be used. 8174 // inlined version can't be used.
8164 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; 8175 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8165 // If there currently can be no elements accessors on the prototype chain, 8176 // If there currently can be no elements accessors on the prototype chain,
8166 // it doesn't mean that there won't be any later. Install a full prototype 8177 // it doesn't mean that there won't be any later. Install a full prototype
8167 // chain check to trap element accessors being installed on the prototype 8178 // chain check to trap element accessors being installed on the prototype
8168 // chain, which would cause elements to go to dictionary mode and result 8179 // chain, which would cause elements to go to dictionary mode and result
8169 // in a map change. 8180 // in a map change.
8170 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 8181 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
8171 BuildCheckPrototypeMaps(prototype, Handle<JSObject>()); 8182 BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
8172 8183
8173 const int argc = expr->arguments()->length(); 8184 const int argc = args_count_no_receiver;
8174 if (argc != 1) return false; 8185 if (argc != 1) return false;
8175 8186
8176 HValue* value_to_push = Pop(); 8187 HValue* value_to_push = Pop();
8177 HValue* array = Pop(); 8188 HValue* array = Pop();
8178 Drop(1); // Drop function. 8189 Drop(1 + drop_extra); // Drop function + extra.
8179 8190
8180 HInstruction* new_size = NULL; 8191 HInstruction* new_size = NULL;
8181 HValue* length = NULL; 8192 HValue* length = NULL;
8182 8193
8183 { 8194 {
8184 NoObservableSideEffectsScope scope(this); 8195 NoObservableSideEffectsScope scope(this);
8185 8196
8186 length = Add<HLoadNamedField>(array, static_cast<HValue*>(NULL), 8197 length = Add<HLoadNamedField>(array, static_cast<HValue*>(NULL),
8187 HObjectAccess::ForArrayLength(elements_kind)); 8198 HObjectAccess::ForArrayLength(elements_kind));
8188 8199
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
8220 // chain check to trap element accessors being installed on the prototype 8231 // chain check to trap element accessors being installed on the prototype
8221 // chain, which would cause elements to go to dictionary mode and result 8232 // chain, which would cause elements to go to dictionary mode and result
8222 // in a map change. 8233 // in a map change.
8223 BuildCheckPrototypeMaps( 8234 BuildCheckPrototypeMaps(
8224 handle(JSObject::cast(receiver_map->prototype()), isolate()), 8235 handle(JSObject::cast(receiver_map->prototype()), isolate()),
8225 Handle<JSObject>::null()); 8236 Handle<JSObject>::null());
8226 8237
8227 // Threshold for fast inlined Array.shift(). 8238 // Threshold for fast inlined Array.shift().
8228 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16)); 8239 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
8229 8240
8230 Drop(expr->arguments()->length()); 8241 Drop(args_count_no_receiver);
8231 HValue* receiver = Pop(); 8242 HValue* receiver = Pop();
8232 HValue* function = Pop(); 8243 HValue* function = Pop();
8244 Drop(drop_extra); // Drop extras after function.
8233 HValue* result; 8245 HValue* result;
8234 8246
8235 { 8247 {
8236 NoObservableSideEffectsScope scope(this); 8248 NoObservableSideEffectsScope scope(this);
8237 8249
8238 HValue* length = Add<HLoadNamedField>( 8250 HValue* length = Add<HLoadNamedField>(
8239 receiver, static_cast<HValue*>(NULL), 8251 receiver, static_cast<HValue*>(NULL),
8240 HObjectAccess::ForArrayLength(kind)); 8252 HObjectAccess::ForArrayLength(kind));
8241 8253
8242 IfBuilder if_lengthiszero(this); 8254 IfBuilder if_lengthiszero(this);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
8334 // it doesn't mean that there won't be any later. Install a full prototype 8346 // it doesn't mean that there won't be any later. Install a full prototype
8335 // chain check to trap element accessors being installed on the prototype 8347 // chain check to trap element accessors being installed on the prototype
8336 // chain, which would cause elements to go to dictionary mode and result 8348 // chain, which would cause elements to go to dictionary mode and result
8337 // in a map change. 8349 // in a map change.
8338 BuildCheckPrototypeMaps( 8350 BuildCheckPrototypeMaps(
8339 handle(JSObject::cast(receiver_map->prototype()), isolate()), 8351 handle(JSObject::cast(receiver_map->prototype()), isolate()),
8340 Handle<JSObject>::null()); 8352 Handle<JSObject>::null());
8341 8353
8342 HValue* search_element = Pop(); 8354 HValue* search_element = Pop();
8343 HValue* receiver = Pop(); 8355 HValue* receiver = Pop();
8344 Drop(1); // Drop function. 8356 Drop(1 + drop_extra); // Drop function + extra.
8345 8357
8346 ArrayIndexOfMode mode = (id == kArrayIndexOf) 8358 ArrayIndexOfMode mode = (id == kArrayIndexOf)
8347 ? kFirstIndexOf : kLastIndexOf; 8359 ? kFirstIndexOf : kLastIndexOf;
8348 HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode); 8360 HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
8349 8361
8350 if (!ast_context()->IsEffect()) Push(index); 8362 if (!ast_context()->IsEffect()) Push(index);
8351 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 8363 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8352 if (!ast_context()->IsEffect()) Drop(1); 8364 if (!ast_context()->IsEffect()) Drop(1);
8353 ast_context()->ReturnValue(index); 8365 ast_context()->ReturnValue(index);
8354 return true; 8366 return true;
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
8531 HInstruction* call = New<HCallWithDescriptor>( 8543 HInstruction* call = New<HCallWithDescriptor>(
8532 code_value, argc + 1, descriptor, 8544 code_value, argc + 1, descriptor,
8533 Vector<HValue*>(op_vals, descriptor->environment_length())); 8545 Vector<HValue*>(op_vals, descriptor->environment_length()));
8534 8546
8535 if (drop_extra) Drop(1); // Drop function. 8547 if (drop_extra) Drop(1); // Drop function.
8536 ast_context()->ReturnInstruction(call, ast_id); 8548 ast_context()->ReturnInstruction(call, ast_id);
8537 return true; 8549 return true;
8538 } 8550 }
8539 8551
8540 8552
8541 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { 8553 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr,
8554 HValue* function,
8555 int arguments_count,
8556 int drop_extra) {
8557 Handle<JSFunction> known_function;
8558 int args_count_no_receiver = arguments_count - 1;
8559 if (function->IsConstant() &&
8560 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8561 known_function = Handle<JSFunction>::cast(
8562 HConstant::cast(function)->handle(isolate()));
8563 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
8564 Drop(drop_extra);
8565 return;
8566 }
8567
8568 Handle<Map> map;
8569 if (TryInlineBuiltinMethodCall(expr, known_function, map,
8570 args_count_no_receiver, drop_extra)) {
8571 if (FLAG_trace_inlining) {
8572 PrintF("Inlining builtin ");
8573 known_function->ShortPrint();
8574 PrintF("\n");
8575 }
8576 return;
8577 }
8578 }
8579
8580 PushArgumentsFromEnvironment(arguments_count);
8581 HInvokeFunction* call = New<HInvokeFunction>(
8582 function, known_function, arguments_count);
8583 Drop(1 + drop_extra); // Function + extra.
8584 ast_context()->ReturnInstruction(call, expr->id());
8585 }
8586
8587
8588 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
8542 ASSERT(expr->expression()->IsProperty()); 8589 ASSERT(expr->expression()->IsProperty());
8543 8590
8544 if (!expr->IsMonomorphic()) { 8591 if (!expr->IsMonomorphic()) {
8545 return false; 8592 return false;
8546 } 8593 }
8594
8547 Handle<Map> function_map = expr->GetReceiverTypes()->first(); 8595 Handle<Map> function_map = expr->GetReceiverTypes()->first();
8548 if (function_map->instance_type() != JS_FUNCTION_TYPE || 8596 if (function_map->instance_type() != JS_FUNCTION_TYPE ||
8549 !expr->target()->shared()->HasBuiltinFunctionId() || 8597 !expr->target()->shared()->HasBuiltinFunctionId()) {
8550 expr->target()->shared()->builtin_function_id() != kFunctionApply) {
8551 return false; 8598 return false;
8552 } 8599 }
8553 8600
8554 if (current_info()->scope()->arguments() == NULL) return false; 8601 switch (expr->target()->shared()->builtin_function_id()) {
8602 case kFunctionCall: {
8603 BuildFunctionCall(expr);
8604 return true;
8605 }
8606 case kFunctionApply: {
8607 // For .apply, only the pattern f.apply(receiver, arguments)
8608 // is supported.
8609 if (current_info()->scope()->arguments() == NULL) return false;
8555 8610
8611 ZoneList<Expression*>* args = expr->arguments();
8612 if (args->length() != 2) return false;
8613
8614 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
8615 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
8616 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
8617 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
8618 BuildFunctionApply(expr);
8619 return true;
8620 }
8621 default: {
8622 return false;
8623 }
8624 }
8625 UNREACHABLE();
8626 }
8627
8628
8629 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
8556 ZoneList<Expression*>* args = expr->arguments(); 8630 ZoneList<Expression*>* args = expr->arguments();
8557 if (args->length() != 2) return false; 8631 CHECK_ALIVE(VisitForValue(args->at(0)));
8558
8559 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
8560 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
8561 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
8562 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
8563
8564 // Found pattern f.apply(receiver, arguments).
8565 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
8566 HValue* receiver = Pop(); // receiver 8632 HValue* receiver = Pop(); // receiver
8567 HValue* function = Pop(); // f 8633 HValue* function = Pop(); // f
8568 Drop(1); // apply 8634 Drop(1); // apply
8569 8635
8636 Handle<Map> function_map = expr->GetReceiverTypes()->first();
8570 HValue* checked_function = AddCheckMap(function, function_map); 8637 HValue* checked_function = AddCheckMap(function, function_map);
8571 8638
8572 if (function_state()->outer() == NULL) { 8639 if (function_state()->outer() == NULL) {
8573 HInstruction* elements = Add<HArgumentsElements>(false); 8640 HInstruction* elements = Add<HArgumentsElements>(false);
8574 HInstruction* length = Add<HArgumentsLength>(elements); 8641 HInstruction* length = Add<HArgumentsLength>(elements);
8575 HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function); 8642 HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
8576 HInstruction* result = New<HApplyArguments>(function, 8643 HInstruction* result = New<HApplyArguments>(function,
8577 wrapped_receiver, 8644 wrapped_receiver,
8578 length, 8645 length,
8579 elements); 8646 elements);
8580 ast_context()->ReturnInstruction(result, expr->id()); 8647 ast_context()->ReturnInstruction(result, expr->id());
8581 return true;
8582 } else { 8648 } else {
8583 // We are inside inlined function and we know exactly what is inside 8649 // We are inside inlined function and we know exactly what is inside
8584 // arguments object. But we need to be able to materialize at deopt. 8650 // arguments object. But we need to be able to materialize at deopt.
8585 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), 8651 ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
8586 function_state()->entry()->arguments_object()->arguments_count()); 8652 function_state()->entry()->arguments_object()->arguments_count());
8587 HArgumentsObject* args = function_state()->entry()->arguments_object(); 8653 HArgumentsObject* args = function_state()->entry()->arguments_object();
8588 const ZoneList<HValue*>* arguments_values = args->arguments_values(); 8654 const ZoneList<HValue*>* arguments_values = args->arguments_values();
8589 int arguments_count = arguments_values->length(); 8655 int arguments_count = arguments_values->length();
8590 Push(function); 8656 Push(function);
8591 Push(BuildWrapReceiver(receiver, checked_function)); 8657 Push(BuildWrapReceiver(receiver, checked_function));
8592 for (int i = 1; i < arguments_count; i++) { 8658 for (int i = 1; i < arguments_count; i++) {
8593 Push(arguments_values->at(i)); 8659 Push(arguments_values->at(i));
8594 } 8660 }
8595 8661 HandleIndirectCall(expr, function, arguments_count, 0);
8596 Handle<JSFunction> known_function;
8597 if (function->IsConstant() &&
8598 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8599 known_function = Handle<JSFunction>::cast(
8600 HConstant::cast(function)->handle(isolate()));
8601 int args_count = arguments_count - 1; // Excluding receiver.
8602 if (TryInlineApply(known_function, expr, args_count)) return true;
8603 }
8604
8605 PushArgumentsFromEnvironment(arguments_count);
8606 HInvokeFunction* call = New<HInvokeFunction>(
8607 function, known_function, arguments_count);
8608 Drop(1); // Function.
8609 ast_context()->ReturnInstruction(call, expr->id());
8610 return true;
8611 } 8662 }
8612 } 8663 }
8613 8664
8614 8665
8666 // f.call(...)
8667 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
8668 HValue* function = Top(); // f
8669 Handle<Map> function_map = expr->GetReceiverTypes()->first();
8670 HValue* checked_function = AddCheckMap(function, function_map);
8671
8672 int drop_extra = 0;
8673 ZoneList<Expression*>* args = expr->arguments();
8674 int args_length = args->length();
8675 if (args_length == 0) {
8676 Drop(2); // function and call
8677 Push(function);
8678 Push(BuildWrapReceiver(
8679 graph()->GetConstantUndefined(), checked_function));
8680 args_length = 1;
8681 } else {
8682 CHECK_ALIVE(VisitForValue(args->at(0)));
8683 Push(BuildWrapReceiver(Pop(), checked_function));
8684 for (int i = 1; i < args_length; i++) {
8685 CHECK_ALIVE(VisitForValue(args->at(i)));
8686 }
8687 drop_extra = 1; // drop call later
8688 }
8689
8690 HandleIndirectCall(expr, function, args_length, drop_extra);
8691 }
8692
8693
8615 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, 8694 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
8616 Handle<JSFunction> target) { 8695 Handle<JSFunction> target) {
8617 SharedFunctionInfo* shared = target->shared(); 8696 SharedFunctionInfo* shared = target->shared();
8618 if (shared->strict_mode() == SLOPPY && !shared->native()) { 8697 if (shared->strict_mode() == SLOPPY && !shared->native()) {
8619 // Cannot embed a direct reference to the global proxy 8698 // Cannot embed a direct reference to the global proxy
8620 // as is it dropped on deserialization. 8699 // as is it dropped on deserialization.
8621 CHECK(!isolate()->serializer_enabled()); 8700 CHECK(!isolate()->serializer_enabled());
8622 Handle<JSObject> global_receiver( 8701 Handle<JSObject> global_receiver(
8623 target->context()->global_object()->global_receiver()); 8702 target->context()->global_object()->global_receiver());
8624 return Add<HConstant>(global_receiver); 8703 return Add<HConstant>(global_receiver);
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
8866 environment()->SetExpressionStackAt(0, function); 8945 environment()->SetExpressionStackAt(0, function);
8867 8946
8868 Push(receiver); 8947 Push(receiver);
8869 8948
8870 if (function->IsConstant() && 8949 if (function->IsConstant() &&
8871 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { 8950 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8872 Handle<JSFunction> known_function = Handle<JSFunction>::cast( 8951 Handle<JSFunction> known_function = Handle<JSFunction>::cast(
8873 HConstant::cast(function)->handle(isolate())); 8952 HConstant::cast(function)->handle(isolate()));
8874 expr->set_target(known_function); 8953 expr->set_target(known_function);
8875 8954
8876 if (TryCallApply(expr)) return; 8955 if (TryIndirectCall(expr)) return;
8877 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8956 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8878 8957
8879 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>(); 8958 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
8880 if (TryInlineBuiltinMethodCall(expr, receiver, map)) { 8959 if (TryInlineBuiltinMethodCall(expr, known_function, map,
8960 expr->arguments()->length())) {
8881 if (FLAG_trace_inlining) { 8961 if (FLAG_trace_inlining) {
8882 PrintF("Inlining builtin "); 8962 PrintF("Inlining builtin ");
8883 known_function->ShortPrint(); 8963 known_function->ShortPrint();
8884 PrintF("\n"); 8964 PrintF("\n");
8885 } 8965 }
8886 return; 8966 return;
8887 } 8967 }
8888 if (TryInlineApiMethodCall(expr, receiver, types)) return; 8968 if (TryInlineApiMethodCall(expr, receiver, types)) return;
8889 8969
8890 // Wrap the receiver if necessary. 8970 // Wrap the receiver if necessary.
(...skipping 3461 matching lines...) Expand 10 before | Expand all | Expand 10 after
12352 if (ShouldProduceTraceOutput()) { 12432 if (ShouldProduceTraceOutput()) {
12353 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 12433 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
12354 } 12434 }
12355 12435
12356 #ifdef DEBUG 12436 #ifdef DEBUG
12357 graph_->Verify(false); // No full verify. 12437 graph_->Verify(false); // No full verify.
12358 #endif 12438 #endif
12359 } 12439 }
12360 12440
12361 } } // namespace v8::internal 12441 } } // 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