| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 MULTIPLE | 105 MULTIPLE |
| 106 }; | 106 }; |
| 107 | 107 |
| 108 HValue* BuildArrayConstructor(ElementsKind kind, | 108 HValue* BuildArrayConstructor(ElementsKind kind, |
| 109 ContextCheckMode context_mode, | 109 ContextCheckMode context_mode, |
| 110 AllocationSiteOverrideMode override_mode, | 110 AllocationSiteOverrideMode override_mode, |
| 111 ArgumentClass argument_class); | 111 ArgumentClass argument_class); |
| 112 HValue* BuildInternalArrayConstructor(ElementsKind kind, | 112 HValue* BuildInternalArrayConstructor(ElementsKind kind, |
| 113 ArgumentClass argument_class); | 113 ArgumentClass argument_class); |
| 114 | 114 |
| 115 void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context, |
| 116 HValue* code_object); |
| 117 void BuildInstallCode(HValue* js_function, HValue* shared_info); |
| 118 void BuildInstallFromOptimizedCodeMap(HValue* js_function, |
| 119 HValue* shared_info, |
| 120 HValue* native_context); |
| 121 |
| 115 private: | 122 private: |
| 116 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 123 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
| 117 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 124 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
| 118 ElementsKind kind); | 125 ElementsKind kind); |
| 119 | 126 |
| 120 SmartArrayPointer<HParameter*> parameters_; | 127 SmartArrayPointer<HParameter*> parameters_; |
| 121 HValue* arguments_length_; | 128 HValue* arguments_length_; |
| 122 CompilationInfoWithZone info_; | 129 CompilationInfoWithZone info_; |
| 123 CodeStubInterfaceDescriptor* descriptor_; | 130 CodeStubInterfaceDescriptor* descriptor_; |
| 124 HContext* context_; | 131 HContext* context_; |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 static_cast<HValue*>(NULL), | 352 static_cast<HValue*>(NULL), |
| 346 FAST_ELEMENTS); | 353 FAST_ELEMENTS); |
| 347 IfBuilder checker(this); | 354 IfBuilder checker(this); |
| 348 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, | 355 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, |
| 349 undefined); | 356 undefined); |
| 350 checker.Then(); | 357 checker.Then(); |
| 351 | 358 |
| 352 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo(); | 359 HObjectAccess access = HObjectAccess::ForAllocationSiteTransitionInfo(); |
| 353 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); | 360 HInstruction* boilerplate = Add<HLoadNamedField>(allocation_site, access); |
| 354 if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { | 361 if (mode == FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS) { |
| 355 HValue* elements = AddLoadElements(boilerplate, NULL); | 362 HValue* elements = AddLoadElements(boilerplate); |
| 356 | 363 |
| 357 IfBuilder if_fixed_cow(this); | 364 IfBuilder if_fixed_cow(this); |
| 358 if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map()); | 365 if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map()); |
| 359 if_fixed_cow.Then(); | 366 if_fixed_cow.Then(); |
| 360 environment()->Push(BuildCloneShallowArray(boilerplate, | 367 environment()->Push(BuildCloneShallowArray(boilerplate, |
| 361 allocation_site, | 368 allocation_site, |
| 362 alloc_site_mode, | 369 alloc_site_mode, |
| 363 FAST_ELEMENTS, | 370 FAST_ELEMENTS, |
| 364 0/*copy-on-write*/)); | 371 0/*copy-on-write*/)); |
| 365 if_fixed_cow.Else(); | 372 if_fixed_cow.Else(); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 | 495 |
| 489 | 496 |
| 490 Handle<Code> CreateAllocationSiteStub::GenerateCode() { | 497 Handle<Code> CreateAllocationSiteStub::GenerateCode() { |
| 491 return DoGenerateCode(this); | 498 return DoGenerateCode(this); |
| 492 } | 499 } |
| 493 | 500 |
| 494 | 501 |
| 495 template <> | 502 template <> |
| 496 HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() { | 503 HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() { |
| 497 HInstruction* load = BuildUncheckedMonomorphicElementAccess( | 504 HInstruction* load = BuildUncheckedMonomorphicElementAccess( |
| 498 GetParameter(0), GetParameter(1), NULL, NULL, | 505 GetParameter(0), GetParameter(1), NULL, |
| 499 casted_stub()->is_js_array(), casted_stub()->elements_kind(), | 506 casted_stub()->is_js_array(), casted_stub()->elements_kind(), |
| 500 false, NEVER_RETURN_HOLE, STANDARD_STORE); | 507 false, NEVER_RETURN_HOLE, STANDARD_STORE); |
| 501 return load; | 508 return load; |
| 502 } | 509 } |
| 503 | 510 |
| 504 | 511 |
| 505 Handle<Code> KeyedLoadFastElementStub::GenerateCode() { | 512 Handle<Code> KeyedLoadFastElementStub::GenerateCode() { |
| 506 return DoGenerateCode(this); | 513 return DoGenerateCode(this); |
| 507 } | 514 } |
| 508 | 515 |
| 509 | 516 |
| 510 template<> | 517 template<> |
| 511 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() { | 518 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() { |
| 512 Representation rep = casted_stub()->representation(); | 519 Representation rep = casted_stub()->representation(); |
| 513 HObjectAccess access = casted_stub()->is_inobject() ? | 520 HObjectAccess access = casted_stub()->is_inobject() ? |
| 514 HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) : | 521 HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) : |
| 515 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); | 522 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); |
| 516 return AddInstruction(BuildLoadNamedField(GetParameter(0), access, NULL)); | 523 return AddInstruction(BuildLoadNamedField(GetParameter(0), access)); |
| 517 } | 524 } |
| 518 | 525 |
| 519 | 526 |
| 520 Handle<Code> LoadFieldStub::GenerateCode() { | 527 Handle<Code> LoadFieldStub::GenerateCode() { |
| 521 return DoGenerateCode(this); | 528 return DoGenerateCode(this); |
| 522 } | 529 } |
| 523 | 530 |
| 524 | 531 |
| 525 template<> | 532 template<> |
| 526 HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() { | 533 HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() { |
| 527 Representation rep = casted_stub()->representation(); | 534 Representation rep = casted_stub()->representation(); |
| 528 HObjectAccess access = casted_stub()->is_inobject() ? | 535 HObjectAccess access = casted_stub()->is_inobject() ? |
| 529 HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) : | 536 HObjectAccess::ForJSObjectOffset(casted_stub()->offset(), rep) : |
| 530 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); | 537 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); |
| 531 return AddInstruction(BuildLoadNamedField(GetParameter(0), access, NULL)); | 538 return AddInstruction(BuildLoadNamedField(GetParameter(0), access)); |
| 532 } | 539 } |
| 533 | 540 |
| 534 | 541 |
| 535 Handle<Code> KeyedLoadFieldStub::GenerateCode() { | 542 Handle<Code> KeyedLoadFieldStub::GenerateCode() { |
| 536 return DoGenerateCode(this); | 543 return DoGenerateCode(this); |
| 537 } | 544 } |
| 538 | 545 |
| 539 | 546 |
| 540 template <> | 547 template <> |
| 541 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() { | 548 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() { |
| 542 BuildUncheckedMonomorphicElementAccess( | 549 BuildUncheckedMonomorphicElementAccess( |
| 543 GetParameter(0), GetParameter(1), GetParameter(2), NULL, | 550 GetParameter(0), GetParameter(1), GetParameter(2), |
| 544 casted_stub()->is_js_array(), casted_stub()->elements_kind(), | 551 casted_stub()->is_js_array(), casted_stub()->elements_kind(), |
| 545 true, NEVER_RETURN_HOLE, casted_stub()->store_mode()); | 552 true, NEVER_RETURN_HOLE, casted_stub()->store_mode()); |
| 546 | 553 |
| 547 return GetParameter(2); | 554 return GetParameter(2); |
| 548 } | 555 } |
| 549 | 556 |
| 550 | 557 |
| 551 Handle<Code> KeyedStoreFastElementStub::GenerateCode() { | 558 Handle<Code> KeyedStoreFastElementStub::GenerateCode() { |
| 552 return DoGenerateCode(this); | 559 return DoGenerateCode(this); |
| 553 } | 560 } |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 Add<HDeoptimize>("Deopt due to --trace-elements-transitions", | 888 Add<HDeoptimize>("Deopt due to --trace-elements-transitions", |
| 882 Deoptimizer::EAGER); | 889 Deoptimizer::EAGER); |
| 883 } else { | 890 } else { |
| 884 info()->MarkAsSavesCallerDoubles(); | 891 info()->MarkAsSavesCallerDoubles(); |
| 885 | 892 |
| 886 BuildTransitionElementsKind(object, map, | 893 BuildTransitionElementsKind(object, map, |
| 887 casted_stub()->from_kind(), | 894 casted_stub()->from_kind(), |
| 888 casted_stub()->to_kind(), | 895 casted_stub()->to_kind(), |
| 889 casted_stub()->is_jsarray()); | 896 casted_stub()->is_jsarray()); |
| 890 | 897 |
| 891 BuildUncheckedMonomorphicElementAccess(object, key, value, NULL, | 898 BuildUncheckedMonomorphicElementAccess(object, key, value, |
| 892 casted_stub()->is_jsarray(), | 899 casted_stub()->is_jsarray(), |
| 893 casted_stub()->to_kind(), | 900 casted_stub()->to_kind(), |
| 894 true, ALLOW_RETURN_HOLE, | 901 true, ALLOW_RETURN_HOLE, |
| 895 casted_stub()->store_mode()); | 902 casted_stub()->store_mode()); |
| 896 } | 903 } |
| 897 | 904 |
| 898 return value; | 905 return value; |
| 899 } | 906 } |
| 900 | 907 |
| 901 | 908 |
| 902 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { | 909 Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { |
| 903 return DoGenerateCode(this); | 910 return DoGenerateCode(this); |
| 904 } | 911 } |
| 905 | 912 |
| 906 | 913 |
| 914 void CodeStubGraphBuilderBase::BuildInstallOptimizedCode( |
| 915 HValue* js_function, |
| 916 HValue* native_context, |
| 917 HValue* code_object) { |
| 918 Counters* counters = isolate()->counters(); |
| 919 AddIncrementCounter(counters->fast_new_closure_install_optimized(), |
| 920 context()); |
| 921 |
| 922 // TODO(fschneider): Idea: store proper code pointers in the optimized code |
| 923 // map and either unmangle them on marking or do nothing as the whole map is |
| 924 // discarded on major GC anyway. |
| 925 Add<HStoreCodeEntry>(js_function, code_object); |
| 926 |
| 927 // Now link a function into a list of optimized functions. |
| 928 HValue* optimized_functions_list = Add<HLoadNamedField>(native_context, |
| 929 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); |
| 930 Add<HStoreNamedField>(js_function, |
| 931 HObjectAccess::ForNextFunctionLinkPointer(), |
| 932 optimized_functions_list); |
| 933 |
| 934 // This store is the only one that should have a write barrier. |
| 935 Add<HStoreNamedField>(native_context, |
| 936 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), |
| 937 js_function); |
| 938 } |
| 939 |
| 940 |
| 941 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, |
| 942 HValue* shared_info) { |
| 943 Add<HStoreNamedField>(js_function, |
| 944 HObjectAccess::ForNextFunctionLinkPointer(), |
| 945 graph()->GetConstantUndefined()); |
| 946 HValue* code_object = Add<HLoadNamedField>(shared_info, |
| 947 HObjectAccess::ForCodeOffset()); |
| 948 Add<HStoreCodeEntry>(js_function, code_object); |
| 949 } |
| 950 |
| 951 |
| 952 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( |
| 953 HValue* js_function, |
| 954 HValue* shared_info, |
| 955 HValue* native_context) { |
| 956 Counters* counters = isolate()->counters(); |
| 957 IfBuilder is_optimized(this); |
| 958 HInstruction* optimized_map = Add<HLoadNamedField>(shared_info, |
| 959 HObjectAccess::ForOptimizedCodeMap()); |
| 960 HValue* null_constant = Add<HConstant>(0); |
| 961 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); |
| 962 is_optimized.Then(); |
| 963 { |
| 964 BuildInstallCode(js_function, shared_info); |
| 965 } |
| 966 is_optimized.Else(); |
| 967 { |
| 968 AddIncrementCounter(counters->fast_new_closure_try_optimized(), context()); |
| 969 // optimized_map points to fixed array of 3-element entries |
| 970 // (native context, optimized code, literals). |
| 971 // Map must never be empty, so check the first elements. |
| 972 Label install_optimized; |
| 973 HValue* first_context_slot = Add<HLoadNamedField>(optimized_map, |
| 974 HObjectAccess::ForFirstContextSlot()); |
| 975 IfBuilder already_in(this); |
| 976 already_in.If<HCompareObjectEqAndBranch>(native_context, |
| 977 first_context_slot); |
| 978 already_in.Then(); |
| 979 { |
| 980 HValue* code_object = Add<HLoadNamedField>(optimized_map, |
| 981 HObjectAccess::ForFirstCodeSlot()); |
| 982 BuildInstallOptimizedCode(js_function, native_context, code_object); |
| 983 } |
| 984 already_in.Else(); |
| 985 { |
| 986 HValue* shared_function_entry_length = |
| 987 Add<HConstant>(SharedFunctionInfo::kEntryLength); |
| 988 LoopBuilder loop_builder(this, |
| 989 context(), |
| 990 LoopBuilder::kPostDecrement, |
| 991 shared_function_entry_length); |
| 992 HValue* array_length = Add<HLoadNamedField>(optimized_map, |
| 993 HObjectAccess::ForFixedArrayLength()); |
| 994 HValue* key = loop_builder.BeginBody(array_length, |
| 995 graph()->GetConstant0(), |
| 996 Token::GT); |
| 997 { |
| 998 // Iterate through the rest of map backwards. |
| 999 // Do not double check first entry. |
| 1000 HValue* second_entry_index = |
| 1001 Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex); |
| 1002 IfBuilder restore_check(this); |
| 1003 restore_check.If<HCompareNumericAndBranch>(key, second_entry_index, |
| 1004 Token::EQ); |
| 1005 restore_check.Then(); |
| 1006 { |
| 1007 // Store the unoptimized code |
| 1008 BuildInstallCode(js_function, shared_info); |
| 1009 loop_builder.Break(); |
| 1010 } |
| 1011 restore_check.Else(); |
| 1012 { |
| 1013 HValue* keyed_minus = AddInstruction(HSub::New(zone(), context(), key, |
| 1014 shared_function_entry_length)); |
| 1015 HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map, |
| 1016 keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1017 IfBuilder done_check(this); |
| 1018 done_check.If<HCompareObjectEqAndBranch>(native_context, |
| 1019 keyed_lookup); |
| 1020 done_check.Then(); |
| 1021 { |
| 1022 // Hit: fetch the optimized code. |
| 1023 HValue* keyed_plus = AddInstruction(HAdd::New(zone(), context(), |
| 1024 keyed_minus, graph()->GetConstant1())); |
| 1025 HValue* code_object = Add<HLoadKeyed>(optimized_map, |
| 1026 keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1027 BuildInstallOptimizedCode(js_function, native_context, code_object); |
| 1028 |
| 1029 // Fall out of the loop |
| 1030 loop_builder.Break(); |
| 1031 } |
| 1032 done_check.Else(); |
| 1033 done_check.End(); |
| 1034 } |
| 1035 restore_check.End(); |
| 1036 } |
| 1037 loop_builder.EndBody(); |
| 1038 } |
| 1039 already_in.End(); |
| 1040 } |
| 1041 is_optimized.End(); |
| 1042 } |
| 1043 |
| 1044 |
| 1045 template<> |
| 1046 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() { |
| 1047 Counters* counters = isolate()->counters(); |
| 1048 Factory* factory = isolate()->factory(); |
| 1049 HInstruction* empty_fixed_array = |
| 1050 Add<HConstant>(factory->empty_fixed_array()); |
| 1051 HValue* shared_info = GetParameter(0); |
| 1052 |
| 1053 // Create a new closure from the given function info in new space |
| 1054 HValue* size = Add<HConstant>(JSFunction::kSize); |
| 1055 HInstruction* js_function = Add<HAllocate>(size, HType::JSObject(), |
| 1056 NOT_TENURED, JS_FUNCTION_TYPE); |
| 1057 AddIncrementCounter(counters->fast_new_closure_total(), context()); |
| 1058 |
| 1059 int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(), |
| 1060 casted_stub()->is_generator()); |
| 1061 |
| 1062 // Compute the function map in the current native context and set that |
| 1063 // as the map of the allocated object. |
| 1064 HInstruction* native_context = BuildGetNativeContext(); |
| 1065 HInstruction* map_slot_value = Add<HLoadNamedField>(native_context, |
| 1066 HObjectAccess::ForContextSlot(map_index)); |
| 1067 Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value); |
| 1068 |
| 1069 // Initialize the rest of the function. |
| 1070 Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(), |
| 1071 empty_fixed_array); |
| 1072 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), |
| 1073 empty_fixed_array); |
| 1074 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
| 1075 empty_fixed_array); |
| 1076 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), |
| 1077 graph()->GetConstantHole()); |
| 1078 Add<HStoreNamedField>(js_function, |
| 1079 HObjectAccess::ForSharedFunctionInfoPointer(), |
| 1080 shared_info); |
| 1081 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), |
| 1082 shared_info); |
| 1083 Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(), |
| 1084 context()); |
| 1085 |
| 1086 // Initialize the code pointer in the function to be the one |
| 1087 // found in the shared function info object. |
| 1088 // But first check if there is an optimized version for our context. |
| 1089 if (FLAG_cache_optimized_code) { |
| 1090 BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context); |
| 1091 } else { |
| 1092 BuildInstallCode(js_function, shared_info); |
| 1093 } |
| 1094 |
| 1095 return js_function; |
| 1096 } |
| 1097 |
| 1098 |
| 1099 Handle<Code> FastNewClosureStub::GenerateCode() { |
| 1100 return DoGenerateCode(this); |
| 1101 } |
| 1102 |
| 1103 |
| 907 } } // namespace v8::internal | 1104 } } // namespace v8::internal |
| OLD | NEW |