OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5523 | 5523 |
5524 | 5524 |
5525 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 5525 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { |
5526 if (lookup_.IsField()) { | 5526 if (lookup_.IsField()) { |
5527 access_ = HObjectAccess::ForField(map, &lookup_, name_); | 5527 access_ = HObjectAccess::ForField(map, &lookup_, name_); |
5528 } else if (lookup_.IsPropertyCallbacks()) { | 5528 } else if (lookup_.IsPropertyCallbacks()) { |
5529 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); | 5529 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); |
5530 if (!callback->IsAccessorPair()) return false; | 5530 if (!callback->IsAccessorPair()) return false; |
5531 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); | 5531 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); |
5532 if (!getter->IsJSFunction()) return false; | 5532 if (!getter->IsJSFunction()) return false; |
5533 Handle<JSFunction> accessor = handle(JSFunction::cast(getter)); | 5533 accessor_ = handle(JSFunction::cast(getter)); |
5534 CallOptimization call_optimization(accessor); | |
5535 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. | |
5536 if (call_optimization.is_simple_api_call()) return false; | |
5537 accessor_ = accessor; | |
5538 } else if (lookup_.IsConstant()) { | 5534 } else if (lookup_.IsConstant()) { |
5539 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); | 5535 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); |
5540 } | 5536 } |
5541 | 5537 |
5542 return true; | 5538 return true; |
5543 } | 5539 } |
5544 | 5540 |
5545 | 5541 |
5546 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 5542 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
5547 Handle<Map> map = this->map(); | 5543 Handle<Map> map = this->map(); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5652 | 5648 |
5653 if (info->lookup()->IsPropertyCallbacks()) { | 5649 if (info->lookup()->IsPropertyCallbacks()) { |
5654 if (NeedsWrappingFor(info->type(), info->accessor())) { | 5650 if (NeedsWrappingFor(info->type(), info->accessor())) { |
5655 HValue* function = Add<HConstant>(info->accessor()); | 5651 HValue* function = Add<HConstant>(info->accessor()); |
5656 Add<HPushArgument>(checked_object); | 5652 Add<HPushArgument>(checked_object); |
5657 return New<HCallFunction>(function, 1, WRAP_AND_CALL); | 5653 return New<HCallFunction>(function, 1, WRAP_AND_CALL); |
5658 } else { | 5654 } else { |
5659 Push(checked_object); | 5655 Push(checked_object); |
5660 if (FLAG_inline_accessors && | 5656 if (FLAG_inline_accessors && |
5661 can_inline_accessor && | 5657 can_inline_accessor && |
5662 TryInlineGetter(info->accessor(), ast_id, return_id)) { | 5658 TryInlineGetter(info->accessor(), |
5659 checked_object, | |
5660 info->map(), | |
5661 ast_id, | |
5662 return_id)) { | |
5663 return NULL; | 5663 return NULL; |
5664 } | 5664 } |
5665 Add<HPushArgument>(Pop()); | 5665 Add<HPushArgument>(Pop()); |
5666 return BuildCallConstantFunction(info->accessor(), 1); | 5666 return BuildCallConstantFunction(info->accessor(), 1); |
5667 } | 5667 } |
5668 } | 5668 } |
5669 | 5669 |
5670 ASSERT(info->lookup()->IsConstant()); | 5670 ASSERT(info->lookup()->IsConstant()); |
5671 return New<HConstant>(info->constant()); | 5671 return New<HConstant>(info->constant()); |
5672 } | 5672 } |
(...skipping 1927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7600 return TryInline(expr->target(), | 7600 return TryInline(expr->target(), |
7601 expr->arguments()->length(), | 7601 expr->arguments()->length(), |
7602 implicit_return_value, | 7602 implicit_return_value, |
7603 expr->id(), | 7603 expr->id(), |
7604 expr->ReturnId(), | 7604 expr->ReturnId(), |
7605 CONSTRUCT_CALL_RETURN); | 7605 CONSTRUCT_CALL_RETURN); |
7606 } | 7606 } |
7607 | 7607 |
7608 | 7608 |
7609 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 7609 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
7610 HValue * receiver, | |
Toon Verwaest
2014/02/04 13:25:31
Remove space between HValue and *
| |
7611 Handle<Map> receiver_map, | |
7610 BailoutId ast_id, | 7612 BailoutId ast_id, |
7611 BailoutId return_id) { | 7613 BailoutId return_id) { |
7614 if (TryInlineApiGetter(getter, receiver, receiver_map, ast_id)) return true; | |
7612 return TryInline(getter, | 7615 return TryInline(getter, |
7613 0, | 7616 0, |
7614 NULL, | 7617 NULL, |
7615 ast_id, | 7618 ast_id, |
7616 return_id, | 7619 return_id, |
7617 GETTER_CALL_RETURN); | 7620 GETTER_CALL_RETURN); |
7618 } | 7621 } |
7619 | 7622 |
7620 | 7623 |
7621 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 7624 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7884 default: | 7887 default: |
7885 // Not yet supported for inlining. | 7888 // Not yet supported for inlining. |
7886 break; | 7889 break; |
7887 } | 7890 } |
7888 return false; | 7891 return false; |
7889 } | 7892 } |
7890 | 7893 |
7891 | 7894 |
7892 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, | 7895 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, |
7893 HValue* receiver) { | 7896 HValue* receiver) { |
7894 return TryInlineApiCall( | 7897 if (!expr->IsMonomorphic()) return false; |
Toon Verwaest
2014/02/04 13:25:31
These checks shouldn't be here, but rather in CanL
| |
7895 expr, receiver, Handle<Map>::null(), true); | 7898 Handle<JSFunction> function = expr->target(); |
7899 int argc = expr->arguments()->length(); | |
7900 Handle<Map> receiver_map = Handle<Map>::null(); | |
7901 return TryInlineApiCall(function, | |
7902 receiver, | |
7903 receiver_map, | |
7904 argc, | |
7905 expr->id(), | |
7906 kCallApiFunction); | |
7896 } | 7907 } |
7897 | 7908 |
7898 | 7909 |
7899 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr, | 7910 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr, |
7900 HValue* receiver, | 7911 HValue* receiver, |
7901 Handle<Map> receiver_map) { | 7912 Handle<Map> receiver_map) { |
7902 return TryInlineApiCall(expr, receiver, receiver_map, false); | 7913 if (!expr->IsMonomorphic()) return false; |
7914 Handle<JSFunction> function = expr->target(); | |
7915 int argc = expr->arguments()->length(); | |
7916 return TryInlineApiCall(function, | |
7917 receiver, | |
7918 receiver_map, | |
7919 argc, | |
7920 expr->id(), | |
7921 kCallApiMethod); | |
7903 } | 7922 } |
7904 | 7923 |
7905 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr, | 7924 |
7906 HValue* receiver, | 7925 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function, |
7907 Handle<Map> receiver_map, | 7926 HValue* receiver, |
7908 bool is_function_call) { | 7927 Handle<Map> receiver_map, |
7909 if (!expr->IsMonomorphic()) return false; | 7928 BailoutId ast_id) { |
7910 CallOptimization optimization(expr->target()); | 7929 return TryInlineApiCall(function, |
7930 receiver, | |
7931 receiver_map, | |
7932 0, | |
7933 ast_id, | |
7934 kCallApiGetter); | |
7935 } | |
7936 | |
7937 | |
7938 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function, | |
7939 HValue* receiver, | |
7940 Handle<Map> receiver_map, | |
7941 int argc, | |
7942 BailoutId ast_id, | |
7943 ApiCallType call_type) { | |
7944 CallOptimization optimization(function); | |
7911 if (!optimization.is_simple_api_call()) return false; | 7945 if (!optimization.is_simple_api_call()) return false; |
7912 Handle<Map> holder_map; | 7946 Handle<Map> holder_map; |
7913 if (is_function_call) { | 7947 if (call_type == kCallApiFunction) { |
7914 // Cannot embed a direct reference to the global proxy map | 7948 // Cannot embed a direct reference to the global proxy map |
7915 // as it maybe dropped on deserialization. | 7949 // as it maybe dropped on deserialization. |
7916 CHECK(!Serializer::enabled()); | 7950 CHECK(!Serializer::enabled()); |
7917 receiver_map = Handle<Map>( | 7951 receiver_map = handle( |
7918 expr->target()->context()->global_object()->global_receiver()->map()); | 7952 function->context()->global_object()->global_receiver()->map()); |
7919 } | 7953 } |
7920 CallOptimization::HolderLookup holder_lookup = | 7954 CallOptimization::HolderLookup holder_lookup = |
7921 CallOptimization::kHolderNotFound; | 7955 CallOptimization::kHolderNotFound; |
7922 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 7956 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
7923 receiver_map, &holder_lookup); | 7957 receiver_map, &holder_lookup); |
7924 if (holder_lookup == CallOptimization::kHolderNotFound) return false; | 7958 if (holder_lookup == CallOptimization::kHolderNotFound) return false; |
7925 | 7959 |
7926 if (FLAG_trace_inlining) { | 7960 if (FLAG_trace_inlining) { |
7927 PrintF("Inlining api function "); | 7961 PrintF("Inlining api function "); |
7928 expr->target()->ShortPrint(); | 7962 function->ShortPrint(); |
7929 PrintF("\n"); | 7963 PrintF("\n"); |
7930 } | 7964 } |
7931 | 7965 |
7932 const int argc = expr->arguments()->length(); | 7966 if (call_type == kCallApiGetter) { |
7933 // Includes receiver. | 7967 ASSERT_EQ(0, argc); |
7934 PushArgumentsFromEnvironment(argc + 1); | 7968 Add<HPushArgument>(Pop()); // Receiver. |
7969 } else { | |
7970 // Includes receiver. | |
7971 PushArgumentsFromEnvironment(argc + 1); | |
7972 } | |
7935 | 7973 |
7936 // Need to ensure the chain between receiver and api_holder is intact | 7974 // Need to ensure the chain between receiver and api_holder is intact |
7937 AddCheckMap(receiver, receiver_map); | 7975 AddCheckMap(receiver, receiver_map); |
7938 if (holder_lookup == CallOptimization::kHolderFound) { | 7976 if (holder_lookup == CallOptimization::kHolderFound) { |
7939 AddCheckPrototypeMaps(api_holder, receiver_map); | 7977 AddCheckPrototypeMaps(api_holder, receiver_map); |
7940 } else { | 7978 } else { |
7941 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); | 7979 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); |
7942 } | 7980 } |
7943 | 7981 |
7944 HValue* holder = NULL; | 7982 HValue* holder = NULL; |
(...skipping 12 matching lines...) Expand all Loading... | |
7957 Handle<Object> call_data_obj(api_call_info->data(), isolate()); | 7995 Handle<Object> call_data_obj(api_call_info->data(), isolate()); |
7958 bool call_data_is_undefined = call_data_obj->IsUndefined(); | 7996 bool call_data_is_undefined = call_data_obj->IsUndefined(); |
7959 HValue* call_data = Add<HConstant>(call_data_obj); | 7997 HValue* call_data = Add<HConstant>(call_data_obj); |
7960 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback())); | 7998 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback())); |
7961 ExternalReference ref = ExternalReference(&fun, | 7999 ExternalReference ref = ExternalReference(&fun, |
7962 ExternalReference::DIRECT_API_CALL, | 8000 ExternalReference::DIRECT_API_CALL, |
7963 isolate()); | 8001 isolate()); |
7964 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); | 8002 HValue* api_function_address = Add<HConstant>(ExternalReference(ref)); |
7965 | 8003 |
7966 HValue* op_vals[] = { | 8004 HValue* op_vals[] = { |
7967 // callee | 8005 Add<HConstant>(function), |
7968 Add<HConstant>(expr->target()), | |
7969 call_data, | 8006 call_data, |
7970 holder, | 8007 holder, |
7971 api_function_address, | 8008 api_function_address, |
7972 context() | 8009 context() |
7973 }; | 8010 }; |
7974 | 8011 |
7975 CallInterfaceDescriptor* descriptor = | 8012 CallInterfaceDescriptor* descriptor = |
7976 isolate()->call_descriptor(Isolate::ApiFunctionCall); | 8013 isolate()->call_descriptor(Isolate::ApiFunctionCall); |
7977 | 8014 |
7978 CallApiFunctionStub stub(true, call_data_is_undefined, argc); | 8015 CallApiFunctionStub stub(true, call_data_is_undefined, argc); |
7979 Handle<Code> code = stub.GetCode(isolate()); | 8016 Handle<Code> code = stub.GetCode(isolate()); |
7980 HConstant* code_value = Add<HConstant>(code); | 8017 HConstant* code_value = Add<HConstant>(code); |
7981 | 8018 |
7982 ASSERT((sizeof(op_vals) / kPointerSize) == | 8019 ASSERT((sizeof(op_vals) / kPointerSize) == |
7983 descriptor->environment_length()); | 8020 descriptor->environment_length()); |
7984 | 8021 |
7985 HInstruction* call = New<HCallWithDescriptor>( | 8022 HInstruction* call = New<HCallWithDescriptor>( |
7986 code_value, argc + 1, descriptor, | 8023 code_value, argc + 1, descriptor, |
7987 Vector<HValue*>(op_vals, descriptor->environment_length())); | 8024 Vector<HValue*>(op_vals, descriptor->environment_length())); |
7988 | 8025 |
7989 Drop(1); // Drop function. | 8026 switch (call_type) { |
7990 ast_context()->ReturnInstruction(call, expr->id()); | 8027 case kCallApiFunction: |
8028 case kCallApiMethod: | |
8029 Drop(1); // Drop function. | |
8030 break; | |
8031 case kCallApiGetter: | |
8032 break; | |
8033 } | |
8034 ast_context()->ReturnInstruction(call, ast_id); | |
7991 return true; | 8035 return true; |
7992 } | 8036 } |
7993 | 8037 |
7994 | 8038 |
7995 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 8039 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { |
7996 ASSERT(expr->expression()->IsProperty()); | 8040 ASSERT(expr->expression()->IsProperty()); |
7997 | 8041 |
7998 if (!expr->IsMonomorphic()) { | 8042 if (!expr->IsMonomorphic()) { |
7999 return false; | 8043 return false; |
8000 } | 8044 } |
(...skipping 3355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11356 if (ShouldProduceTraceOutput()) { | 11400 if (ShouldProduceTraceOutput()) { |
11357 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11401 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11358 } | 11402 } |
11359 | 11403 |
11360 #ifdef DEBUG | 11404 #ifdef DEBUG |
11361 graph_->Verify(false); // No full verify. | 11405 graph_->Verify(false); // No full verify. |
11362 #endif | 11406 #endif |
11363 } | 11407 } |
11364 | 11408 |
11365 } } // namespace v8::internal | 11409 } } // namespace v8::internal |
OLD | NEW |