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

Side by Side Diff: src/hydrogen.cc

Issue 151163005: A64: Synchronize with r16356. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/hydrogen-bch.cc » ('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 // 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 812 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 } 823 }
824 builder_->set_current_block(first_true_block_); 824 builder_->set_current_block(first_true_block_);
825 } 825 }
826 826
827 827
828 void HGraphBuilder::IfBuilder::Else() { 828 void HGraphBuilder::IfBuilder::Else() {
829 ASSERT(did_then_); 829 ASSERT(did_then_);
830 ASSERT(!captured_); 830 ASSERT(!captured_);
831 ASSERT(!finished_); 831 ASSERT(!finished_);
832 last_true_block_ = builder_->current_block(); 832 last_true_block_ = builder_->current_block();
833 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished());
834 builder_->set_current_block(first_false_block_); 833 builder_->set_current_block(first_false_block_);
835 did_else_ = true; 834 did_else_ = true;
836 } 835 }
837 836
838 837
839 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { 838 void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
840 ASSERT(did_then_); 839 ASSERT(did_then_);
841 if (did_else_) { 840 if (did_else_) {
842 deopt_else_ = true; 841 deopt_else_ = true;
843 } else { 842 } else {
(...skipping 15 matching lines...) Expand all
859 } 858 }
860 } 859 }
861 860
862 861
863 void HGraphBuilder::IfBuilder::End() { 862 void HGraphBuilder::IfBuilder::End() {
864 if (!captured_) { 863 if (!captured_) {
865 ASSERT(did_then_); 864 ASSERT(did_then_);
866 if (!did_else_) { 865 if (!did_else_) {
867 last_true_block_ = builder_->current_block(); 866 last_true_block_ = builder_->current_block();
868 } 867 }
869 if (first_true_block_ == NULL) { 868 if (last_true_block_ == NULL || last_true_block_->IsFinished()) {
869 ASSERT(did_else_);
870 // Return on true. Nothing to do, just continue the false block. 870 // Return on true. Nothing to do, just continue the false block.
871 } else if (first_false_block_ == NULL) { 871 } else if (first_false_block_ == NULL ||
872 (did_else_ && builder_->current_block()->IsFinished())) {
872 // Deopt on false. Nothing to do except switching to the true block. 873 // Deopt on false. Nothing to do except switching to the true block.
873 builder_->set_current_block(last_true_block_); 874 builder_->set_current_block(last_true_block_);
874 } else { 875 } else {
875 merge_block_ = builder_->graph()->CreateBasicBlock(); 876 merge_block_ = builder_->graph()->CreateBasicBlock();
876 ASSERT(!finished_); 877 ASSERT(!finished_);
877 if (!did_else_) Else(); 878 if (!did_else_) Else();
878 ASSERT(!last_true_block_->IsFinished()); 879 ASSERT(!last_true_block_->IsFinished());
879 HBasicBlock* last_false_block = builder_->current_block(); 880 HBasicBlock* last_false_block = builder_->current_block();
880 ASSERT(!last_false_block->IsFinished()); 881 ASSERT(!last_false_block->IsFinished());
881 if (deopt_then_) { 882 if (deopt_then_) {
(...skipping 19 matching lines...) Expand all
901 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 902 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
902 HValue* context, 903 HValue* context,
903 LoopBuilder::Direction direction) 904 LoopBuilder::Direction direction)
904 : builder_(builder), 905 : builder_(builder),
905 context_(context), 906 context_(context),
906 direction_(direction), 907 direction_(direction),
907 finished_(false) { 908 finished_(false) {
908 header_block_ = builder->CreateLoopHeaderBlock(); 909 header_block_ = builder->CreateLoopHeaderBlock();
909 body_block_ = NULL; 910 body_block_ = NULL;
910 exit_block_ = NULL; 911 exit_block_ = NULL;
912 exit_trampoline_block_ = NULL;
913 increment_amount_ = builder_->graph()->GetConstant1();
911 } 914 }
912 915
913 916
917 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
918 HValue* context,
919 LoopBuilder::Direction direction,
920 HValue* increment_amount)
921 : builder_(builder),
922 context_(context),
923 direction_(direction),
924 finished_(false) {
925 header_block_ = builder->CreateLoopHeaderBlock();
926 body_block_ = NULL;
927 exit_block_ = NULL;
928 exit_trampoline_block_ = NULL;
929 increment_amount_ = increment_amount;
930 }
931
932
914 HValue* HGraphBuilder::LoopBuilder::BeginBody( 933 HValue* HGraphBuilder::LoopBuilder::BeginBody(
915 HValue* initial, 934 HValue* initial,
916 HValue* terminating, 935 HValue* terminating,
917 Token::Value token) { 936 Token::Value token) {
918 HEnvironment* env = builder_->environment(); 937 HEnvironment* env = builder_->environment();
919 phi_ = header_block_->AddNewPhi(env->values()->length()); 938 phi_ = header_block_->AddNewPhi(env->values()->length());
920 phi_->AddInput(initial); 939 phi_->AddInput(initial);
921 env->Push(initial); 940 env->Push(initial);
922 builder_->current_block()->GotoNoSimulate(header_block_); 941 builder_->current_block()->GotoNoSimulate(header_block_);
923 942
924 HEnvironment* body_env = env->Copy(); 943 HEnvironment* body_env = env->Copy();
925 HEnvironment* exit_env = env->Copy(); 944 HEnvironment* exit_env = env->Copy();
945 // Remove the phi from the expression stack
946 body_env->Pop();
947 exit_env->Pop();
926 body_block_ = builder_->CreateBasicBlock(body_env); 948 body_block_ = builder_->CreateBasicBlock(body_env);
927 exit_block_ = builder_->CreateBasicBlock(exit_env); 949 exit_block_ = builder_->CreateBasicBlock(exit_env);
928 // Remove the phi from the expression stack
929 body_env->Pop();
930 950
931 builder_->set_current_block(header_block_); 951 builder_->set_current_block(header_block_);
952 env->Pop();
932 HCompareNumericAndBranch* compare = 953 HCompareNumericAndBranch* compare =
933 new(zone()) HCompareNumericAndBranch(phi_, terminating, token); 954 new(zone()) HCompareNumericAndBranch(phi_, terminating, token);
934 compare->SetSuccessorAt(0, body_block_); 955 compare->SetSuccessorAt(0, body_block_);
935 compare->SetSuccessorAt(1, exit_block_); 956 compare->SetSuccessorAt(1, exit_block_);
936 builder_->current_block()->Finish(compare); 957 builder_->current_block()->Finish(compare);
937 958
938 builder_->set_current_block(body_block_); 959 builder_->set_current_block(body_block_);
939 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { 960 if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
940 HValue* one = builder_->graph()->GetConstant1(); 961 HValue* one = builder_->graph()->GetConstant1();
941 if (direction_ == kPreIncrement) { 962 if (direction_ == kPreIncrement) {
942 increment_ = HAdd::New(zone(), context_, phi_, one); 963 increment_ = HAdd::New(zone(), context_, phi_, one);
943 } else { 964 } else {
944 increment_ = HSub::New(zone(), context_, phi_, one); 965 increment_ = HSub::New(zone(), context_, phi_, one);
945 } 966 }
946 increment_->ClearFlag(HValue::kCanOverflow); 967 increment_->ClearFlag(HValue::kCanOverflow);
947 builder_->AddInstruction(increment_); 968 builder_->AddInstruction(increment_);
948 return increment_; 969 return increment_;
949 } else { 970 } else {
950 return phi_; 971 return phi_;
951 } 972 }
952 } 973 }
953 974
954 975
976 void HGraphBuilder::LoopBuilder::Break() {
977 if (exit_trampoline_block_ == NULL) {
978 // Its the first time we saw a break.
979 HEnvironment* env = exit_block_->last_environment()->Copy();
980 exit_trampoline_block_ = builder_->CreateBasicBlock(env);
981 exit_block_->GotoNoSimulate(exit_trampoline_block_);
982 }
983
984 builder_->current_block()->GotoNoSimulate(exit_trampoline_block_);
985 }
986
987
955 void HGraphBuilder::LoopBuilder::EndBody() { 988 void HGraphBuilder::LoopBuilder::EndBody() {
956 ASSERT(!finished_); 989 ASSERT(!finished_);
957 990
958 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { 991 if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
959 HValue* one = builder_->graph()->GetConstant1();
960 if (direction_ == kPostIncrement) { 992 if (direction_ == kPostIncrement) {
961 increment_ = HAdd::New(zone(), context_, phi_, one); 993 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
962 } else { 994 } else {
963 increment_ = HSub::New(zone(), context_, phi_, one); 995 increment_ = HSub::New(zone(), context_, phi_, increment_amount_);
964 } 996 }
965 increment_->ClearFlag(HValue::kCanOverflow); 997 increment_->ClearFlag(HValue::kCanOverflow);
966 builder_->AddInstruction(increment_); 998 builder_->AddInstruction(increment_);
967 } 999 }
968 1000
969 // Push the new increment value on the expression stack to merge into the phi. 1001 // Push the new increment value on the expression stack to merge into the phi.
970 builder_->environment()->Push(increment_); 1002 builder_->environment()->Push(increment_);
971 HBasicBlock* last_block = builder_->current_block(); 1003 HBasicBlock* last_block = builder_->current_block();
972 last_block->GotoNoSimulate(header_block_); 1004 last_block->GotoNoSimulate(header_block_);
973 header_block_->loop_information()->RegisterBackEdge(last_block); 1005 header_block_->loop_information()->RegisterBackEdge(last_block);
974 1006
975 builder_->set_current_block(exit_block_); 1007 if (exit_trampoline_block_ != NULL) {
976 // Pop the phi from the expression stack 1008 builder_->set_current_block(exit_trampoline_block_);
977 builder_->environment()->Pop(); 1009 } else {
1010 builder_->set_current_block(exit_block_);
1011 }
978 finished_ = true; 1012 finished_ = true;
979 } 1013 }
980 1014
981 1015
982 HGraph* HGraphBuilder::CreateGraph() { 1016 HGraph* HGraphBuilder::CreateGraph() {
983 graph_ = new(zone()) HGraph(info_); 1017 graph_ = new(zone()) HGraph(info_);
984 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); 1018 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
985 CompilationPhase phase("H_Block building", info_); 1019 CompilationPhase phase("H_Block building", info_);
986 set_current_block(graph()->entry_block()); 1020 set_current_block(graph()->entry_block());
987 if (!BuildGraph()) return NULL; 1021 if (!BuildGraph()) return NULL;
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1186 ElementsKind to_kind, 1220 ElementsKind to_kind,
1187 bool is_jsarray) { 1221 bool is_jsarray) {
1188 ASSERT(!IsFastHoleyElementsKind(from_kind) || 1222 ASSERT(!IsFastHoleyElementsKind(from_kind) ||
1189 IsFastHoleyElementsKind(to_kind)); 1223 IsFastHoleyElementsKind(to_kind));
1190 1224
1191 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { 1225 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
1192 Add<HTrapAllocationMemento>(object); 1226 Add<HTrapAllocationMemento>(object);
1193 } 1227 }
1194 1228
1195 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { 1229 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
1196 HInstruction* elements = AddLoadElements(object, NULL); 1230 HInstruction* elements = AddLoadElements(object);
1197 1231
1198 HInstruction* empty_fixed_array = Add<HConstant>( 1232 HInstruction* empty_fixed_array = Add<HConstant>(
1199 isolate()->factory()->empty_fixed_array()); 1233 isolate()->factory()->empty_fixed_array());
1200 1234
1201 IfBuilder if_builder(this); 1235 IfBuilder if_builder(this);
1202 1236
1203 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); 1237 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1204 1238
1205 if_builder.Then(); 1239 if_builder.Then();
1206 1240
1207 HInstruction* elements_length = AddLoadFixedArrayLength(elements); 1241 HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1208 1242
1209 HInstruction* array_length = is_jsarray 1243 HInstruction* array_length = is_jsarray
1210 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind)) 1244 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind))
1211 : elements_length; 1245 : elements_length;
1212 1246
1213 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, 1247 BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1214 array_length, elements_length); 1248 array_length, elements_length);
1215 1249
1216 if_builder.End(); 1250 if_builder.End();
1217 } 1251 }
1218 1252
1219 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); 1253 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1220 } 1254 }
1221 1255
1222 1256
1223 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1257 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
1224 HValue* object, 1258 HValue* checked_object,
1225 HValue* key, 1259 HValue* key,
1226 HValue* val, 1260 HValue* val,
1227 HCheckMaps* mapcheck,
1228 bool is_js_array, 1261 bool is_js_array,
1229 ElementsKind elements_kind, 1262 ElementsKind elements_kind,
1230 bool is_store, 1263 bool is_store,
1231 LoadKeyedHoleMode load_mode, 1264 LoadKeyedHoleMode load_mode,
1232 KeyedAccessStoreMode store_mode) { 1265 KeyedAccessStoreMode store_mode) {
1233 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); 1266 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
1234 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 1267 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
1235 // on a HElementsTransition instruction. The flag can also be removed if the 1268 // on a HElementsTransition instruction. The flag can also be removed if the
1236 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 1269 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
1237 // ElementsKind transitions. Finally, the dependency can be removed for stores 1270 // ElementsKind transitions. Finally, the dependency can be removed for stores
1238 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 1271 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
1239 // generated store code. 1272 // generated store code.
1240 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 1273 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
1241 (elements_kind == FAST_ELEMENTS && is_store)) { 1274 (elements_kind == FAST_ELEMENTS && is_store)) {
1242 if (mapcheck != NULL) { 1275 checked_object->ClearGVNFlag(kDependsOnElementsKind);
1243 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
1244 }
1245 } 1276 }
1277
1246 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 1278 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
1247 bool fast_elements = IsFastObjectElementsKind(elements_kind); 1279 bool fast_elements = IsFastObjectElementsKind(elements_kind);
1248 HValue* elements = AddLoadElements(object, mapcheck); 1280 HValue* elements = AddLoadElements(checked_object);
1249 if (is_store && (fast_elements || fast_smi_only_elements) && 1281 if (is_store && (fast_elements || fast_smi_only_elements) &&
1250 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 1282 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1251 HCheckMaps* check_cow_map = Add<HCheckMaps>( 1283 HCheckMaps* check_cow_map = Add<HCheckMaps>(
1252 elements, isolate()->factory()->fixed_array_map(), top_info()); 1284 elements, isolate()->factory()->fixed_array_map(), top_info());
1253 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1285 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1254 } 1286 }
1255 HInstruction* length = NULL; 1287 HInstruction* length = NULL;
1256 if (is_js_array) { 1288 if (is_js_array) {
1257 length = Add<HLoadNamedField>(object, 1289 length = Add<HLoadNamedField>(
1258 HObjectAccess::ForArrayLength(elements_kind), mapcheck); 1290 checked_object, HObjectAccess::ForArrayLength(elements_kind));
1259 } else { 1291 } else {
1260 length = AddLoadFixedArrayLength(elements); 1292 length = AddLoadFixedArrayLength(elements);
1261 } 1293 }
1262 length->set_type(HType::Smi()); 1294 length->set_type(HType::Smi());
1263 HValue* checked_key = NULL; 1295 HValue* checked_key = NULL;
1264 if (IsExternalArrayElementsKind(elements_kind)) { 1296 if (IsExternalArrayElementsKind(elements_kind)) {
1265 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 1297 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
1266 NoObservableSideEffectsScope no_effects(this); 1298 NoObservableSideEffectsScope no_effects(this);
1267 HLoadExternalArrayPointer* external_elements = 1299 HLoadExternalArrayPointer* external_elements =
1268 Add<HLoadExternalArrayPointer>(elements); 1300 Add<HLoadExternalArrayPointer>(elements);
1269 IfBuilder length_checker(this); 1301 IfBuilder length_checker(this);
1270 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 1302 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
1271 length_checker.Then(); 1303 length_checker.Then();
1272 IfBuilder negative_checker(this); 1304 IfBuilder negative_checker(this);
1273 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 1305 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
1274 key, graph()->GetConstant0(), Token::GTE); 1306 key, graph()->GetConstant0(), Token::GTE);
1275 negative_checker.Then(); 1307 negative_checker.Then();
1276 HInstruction* result = AddExternalArrayElementAccess( 1308 HInstruction* result = AddExternalArrayElementAccess(
1277 external_elements, key, val, bounds_check, elements_kind, is_store); 1309 external_elements, key, val, bounds_check, elements_kind, is_store);
1278 negative_checker.ElseDeopt("Negative key encountered"); 1310 negative_checker.ElseDeopt("Negative key encountered");
1279 length_checker.End(); 1311 length_checker.End();
1280 return result; 1312 return result;
1281 } else { 1313 } else {
1282 ASSERT(store_mode == STANDARD_STORE); 1314 ASSERT(store_mode == STANDARD_STORE);
1283 checked_key = Add<HBoundsCheck>(key, length); 1315 checked_key = Add<HBoundsCheck>(key, length);
1284 HLoadExternalArrayPointer* external_elements = 1316 HLoadExternalArrayPointer* external_elements =
1285 Add<HLoadExternalArrayPointer>(elements); 1317 Add<HLoadExternalArrayPointer>(elements);
1286 return AddExternalArrayElementAccess( 1318 return AddExternalArrayElementAccess(
1287 external_elements, checked_key, val, 1319 external_elements, checked_key, val,
1288 mapcheck, elements_kind, is_store); 1320 checked_object, elements_kind, is_store);
1289 } 1321 }
1290 } 1322 }
1291 ASSERT(fast_smi_only_elements || 1323 ASSERT(fast_smi_only_elements ||
1292 fast_elements || 1324 fast_elements ||
1293 IsFastDoubleElementsKind(elements_kind)); 1325 IsFastDoubleElementsKind(elements_kind));
1294 1326
1295 // In case val is stored into a fast smi array, assure that the value is a smi 1327 // In case val is stored into a fast smi array, assure that the value is a smi
1296 // before manipulating the backing store. Otherwise the actual store may 1328 // before manipulating the backing store. Otherwise the actual store may
1297 // deopt, leaving the backing store in an invalid state. 1329 // deopt, leaving the backing store in an invalid state.
1298 if (is_store && IsFastSmiElementsKind(elements_kind) && 1330 if (is_store && IsFastSmiElementsKind(elements_kind) &&
1299 !val->type().IsSmi()) { 1331 !val->type().IsSmi()) {
1300 val = Add<HForceRepresentation>(val, Representation::Smi()); 1332 val = Add<HForceRepresentation>(val, Representation::Smi());
1301 } 1333 }
1302 1334
1303 if (IsGrowStoreMode(store_mode)) { 1335 if (IsGrowStoreMode(store_mode)) {
1304 NoObservableSideEffectsScope no_effects(this); 1336 NoObservableSideEffectsScope no_effects(this);
1305 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, 1337 elements = BuildCheckForCapacityGrow(checked_object, elements,
1306 length, key, is_js_array); 1338 elements_kind, length, key,
1339 is_js_array);
1307 checked_key = key; 1340 checked_key = key;
1308 } else { 1341 } else {
1309 checked_key = Add<HBoundsCheck>(key, length); 1342 checked_key = Add<HBoundsCheck>(key, length);
1310 1343
1311 if (is_store && (fast_elements || fast_smi_only_elements)) { 1344 if (is_store && (fast_elements || fast_smi_only_elements)) {
1312 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 1345 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1313 NoObservableSideEffectsScope no_effects(this); 1346 NoObservableSideEffectsScope no_effects(this);
1314 1347 elements = BuildCopyElementsOnWrite(checked_object, elements,
1315 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, 1348 elements_kind, length);
1316 length);
1317 } else { 1349 } else {
1318 HCheckMaps* check_cow_map = Add<HCheckMaps>( 1350 HCheckMaps* check_cow_map = Add<HCheckMaps>(
1319 elements, isolate()->factory()->fixed_array_map(), 1351 elements, isolate()->factory()->fixed_array_map(),
1320 top_info()); 1352 top_info());
1321 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1353 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1322 } 1354 }
1323 } 1355 }
1324 } 1356 }
1325 return AddFastElementAccess(elements, checked_key, val, mapcheck, 1357 return AddFastElementAccess(elements, checked_key, val, checked_object,
1326 elements_kind, is_store, load_mode, store_mode); 1358 elements_kind, is_store, load_mode, store_mode);
1327 } 1359 }
1328 1360
1329 1361
1330 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, 1362 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
1331 HValue* capacity) { 1363 HValue* capacity) {
1332 int elements_size; 1364 int elements_size;
1333 InstanceType instance_type; 1365 InstanceType instance_type;
1334 1366
1335 if (IsFastDoubleElementsKind(kind)) { 1367 if (IsFastDoubleElementsKind(kind)) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 UNREACHABLE(); 1520 UNREACHABLE();
1489 return NULL; 1521 return NULL;
1490 } 1522 }
1491 } 1523 }
1492 // It's an element load (!is_store). 1524 // It's an element load (!is_store).
1493 return Add<HLoadKeyed>( 1525 return Add<HLoadKeyed>(
1494 elements, checked_key, load_dependency, elements_kind, load_mode); 1526 elements, checked_key, load_dependency, elements_kind, load_mode);
1495 } 1527 }
1496 1528
1497 1529
1498 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, 1530 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) {
1499 HValue* typecheck) { 1531 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer());
1500 return Add<HLoadNamedField>(object,
1501 HObjectAccess::ForElementsPointer(),
1502 typecheck);
1503 } 1532 }
1504 1533
1505 1534
1506 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { 1535 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) {
1507 return Add<HLoadNamedField>(object, 1536 return Add<HLoadNamedField>(object,
1508 HObjectAccess::ForFixedArrayLength()); 1537 HObjectAccess::ForFixedArrayLength());
1509 } 1538 }
1510 1539
1511 1540
1512 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { 1541 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 } 1737 }
1709 1738
1710 // Create an allocation site info if requested. 1739 // Create an allocation site info if requested.
1711 if (mode == TRACK_ALLOCATION_SITE) { 1740 if (mode == TRACK_ALLOCATION_SITE) {
1712 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); 1741 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site);
1713 } 1742 }
1714 1743
1715 if (length > 0) { 1744 if (length > 0) {
1716 // Get hold of the elements array of the boilerplate and setup the 1745 // Get hold of the elements array of the boilerplate and setup the
1717 // elements pointer in the resulting object. 1746 // elements pointer in the resulting object.
1718 HValue* boilerplate_elements = AddLoadElements(boilerplate, NULL); 1747 HValue* boilerplate_elements = AddLoadElements(boilerplate);
1719 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); 1748 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset);
1720 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), 1749 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
1721 object_elements); 1750 object_elements);
1722 1751
1723 // Copy the elements array header. 1752 // Copy the elements array header.
1724 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { 1753 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
1725 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); 1754 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
1726 Add<HStoreNamedField>(object_elements, access, 1755 Add<HStoreNamedField>(object_elements, access,
1727 Add<HLoadNamedField>(boilerplate_elements, access)); 1756 Add<HLoadNamedField>(boilerplate_elements, access));
1728 } 1757 }
(...skipping 13 matching lines...) Expand all
1742 return object; 1771 return object;
1743 } 1772 }
1744 1773
1745 1774
1746 void HGraphBuilder::BuildCompareNil( 1775 void HGraphBuilder::BuildCompareNil(
1747 HValue* value, 1776 HValue* value,
1748 Handle<Type> type, 1777 Handle<Type> type,
1749 int position, 1778 int position,
1750 HIfContinuation* continuation) { 1779 HIfContinuation* continuation) {
1751 IfBuilder if_nil(this, position); 1780 IfBuilder if_nil(this, position);
1752 bool needs_or = false; 1781 bool some_case_handled = false;
1782 bool some_case_missing = false;
1783
1753 if (type->Maybe(Type::Null())) { 1784 if (type->Maybe(Type::Null())) {
1754 if (needs_or) if_nil.Or(); 1785 if (some_case_handled) if_nil.Or();
1755 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); 1786 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
1756 needs_or = true; 1787 some_case_handled = true;
1788 } else {
1789 some_case_missing = true;
1757 } 1790 }
1791
1758 if (type->Maybe(Type::Undefined())) { 1792 if (type->Maybe(Type::Undefined())) {
1759 if (needs_or) if_nil.Or(); 1793 if (some_case_handled) if_nil.Or();
1760 if_nil.If<HCompareObjectEqAndBranch>(value, 1794 if_nil.If<HCompareObjectEqAndBranch>(value,
1761 graph()->GetConstantUndefined()); 1795 graph()->GetConstantUndefined());
1762 needs_or = true; 1796 some_case_handled = true;
1797 } else {
1798 some_case_missing = true;
1763 } 1799 }
1800
1764 if (type->Maybe(Type::Undetectable())) { 1801 if (type->Maybe(Type::Undetectable())) {
1765 if (needs_or) if_nil.Or(); 1802 if (some_case_handled) if_nil.Or();
1766 if_nil.If<HIsUndetectableAndBranch>(value); 1803 if_nil.If<HIsUndetectableAndBranch>(value);
1804 some_case_handled = true;
1767 } else { 1805 } else {
1806 some_case_missing = true;
1807 }
1808
1809 if (some_case_missing) {
1768 if_nil.Then(); 1810 if_nil.Then();
1769 if_nil.Else(); 1811 if_nil.Else();
1770 if (type->NumClasses() == 1) { 1812 if (type->NumClasses() == 1) {
1771 BuildCheckHeapObject(value); 1813 BuildCheckHeapObject(value);
1772 // For ICs, the map checked below is a sentinel map that gets replaced by 1814 // For ICs, the map checked below is a sentinel map that gets replaced by
1773 // the monomorphic map when the code is used as a template to generate a 1815 // the monomorphic map when the code is used as a template to generate a
1774 // new IC. For optimized functions, there is no sentinel map, the map 1816 // new IC. For optimized functions, there is no sentinel map, the map
1775 // emitted below is the actual monomorphic map. 1817 // emitted below is the actual monomorphic map.
1776 BuildCheckMap(value, type->Classes().Current()); 1818 BuildCheckMap(value, type->Classes().Current());
1777 } else { 1819 } else {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1841 constructor_function_(constructor_function) { 1883 constructor_function_(constructor_function) {
1842 } 1884 }
1843 1885
1844 1886
1845 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { 1887 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
1846 if (kind_ == GetInitialFastElementsKind()) { 1888 if (kind_ == GetInitialFastElementsKind()) {
1847 // No need for a context lookup if the kind_ matches the initial 1889 // No need for a context lookup if the kind_ matches the initial
1848 // map, because we can just load the map in that case. 1890 // map, because we can just load the map in that case.
1849 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 1891 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1850 return builder()->AddInstruction( 1892 return builder()->AddInstruction(
1851 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); 1893 builder()->BuildLoadNamedField(constructor_function_, access));
1852 } 1894 }
1853 1895
1854 HInstruction* native_context = builder()->BuildGetNativeContext(); 1896 HInstruction* native_context = builder()->BuildGetNativeContext();
1855 HInstruction* index = builder()->Add<HConstant>( 1897 HInstruction* index = builder()->Add<HConstant>(
1856 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 1898 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
1857 1899
1858 HInstruction* map_array = builder()->Add<HLoadKeyed>( 1900 HInstruction* map_array = builder()->Add<HLoadKeyed>(
1859 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 1901 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1860 1902
1861 HInstruction* kind_index = builder()->Add<HConstant>(kind_); 1903 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
1862 1904
1863 return builder()->Add<HLoadKeyed>( 1905 return builder()->Add<HLoadKeyed>(
1864 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 1906 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1865 } 1907 }
1866 1908
1867 1909
1868 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { 1910 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
1869 // Find the map near the constructor function 1911 // Find the map near the constructor function
1870 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 1912 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1871 return builder()->AddInstruction( 1913 return builder()->AddInstruction(
1872 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); 1914 builder()->BuildLoadNamedField(constructor_function_, access));
1873 } 1915 }
1874 1916
1875 1917
1876 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( 1918 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
1877 HValue* length_node) { 1919 HValue* length_node) {
1878 ASSERT(length_node != NULL); 1920 ASSERT(length_node != NULL);
1879 1921
1880 int base_size = JSArray::kSize; 1922 int base_size = JSArray::kSize;
1881 if (mode_ == TRACK_ALLOCATION_SITE) { 1923 if (mode_ == TRACK_ALLOCATION_SITE) {
1882 base_size += AllocationMemento::kSize; 1924 base_size += AllocationMemento::kSize;
(...skipping 2424 matching lines...) Expand 10 before | Expand all | Expand 10 after
4307 // TODO(mvstanton): This heuristic is only a temporary solution. In the 4349 // TODO(mvstanton): This heuristic is only a temporary solution. In the
4308 // end, we want to quit creating allocation site info after a certain number 4350 // end, we want to quit creating allocation site info after a certain number
4309 // of GCs for a call site. 4351 // of GCs for a call site.
4310 AllocationSiteMode mode = AllocationSite::GetMode( 4352 AllocationSiteMode mode = AllocationSite::GetMode(
4311 boilerplate_elements_kind); 4353 boilerplate_elements_kind);
4312 4354
4313 // Check whether to use fast or slow deep-copying for boilerplate. 4355 // Check whether to use fast or slow deep-copying for boilerplate.
4314 int data_size = 0; 4356 int data_size = 0;
4315 int pointer_size = 0; 4357 int pointer_size = 0;
4316 int max_properties = kMaxFastLiteralProperties; 4358 int max_properties = kMaxFastLiteralProperties;
4317 HCheckMaps* type_check = NULL;
4318 if (IsFastLiteral(original_boilerplate_object, 4359 if (IsFastLiteral(original_boilerplate_object,
4319 kMaxFastLiteralDepth, 4360 kMaxFastLiteralDepth,
4320 &max_properties, 4361 &max_properties,
4321 &data_size, 4362 &data_size,
4322 &pointer_size)) { 4363 &pointer_size)) {
4323 if (mode == TRACK_ALLOCATION_SITE) { 4364 if (mode == TRACK_ALLOCATION_SITE) {
4324 pointer_size += AllocationMemento::kSize; 4365 pointer_size += AllocationMemento::kSize;
4325 } 4366 }
4326 4367
4327 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); 4368 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object);
(...skipping 17 matching lines...) Expand all
4345 4386
4346 Runtime::FunctionId function_id = (expr->depth() > 1) 4387 Runtime::FunctionId function_id = (expr->depth() > 1)
4347 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; 4388 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow;
4348 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), 4389 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
4349 Runtime::FunctionForId(function_id), 4390 Runtime::FunctionForId(function_id),
4350 3); 4391 3);
4351 4392
4352 // De-opt if elements kind changed from boilerplate_elements_kind. 4393 // De-opt if elements kind changed from boilerplate_elements_kind.
4353 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), 4394 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(),
4354 isolate()); 4395 isolate());
4355 type_check = Add<HCheckMaps>(literal, map, top_info()); 4396 literal = Add<HCheckMaps>(literal, map, top_info());
4356 } 4397 }
4357 4398
4358 // The array is expected in the bailout environment during computation 4399 // The array is expected in the bailout environment during computation
4359 // of the property values and is the value of the entire expression. 4400 // of the property values and is the value of the entire expression.
4360 Push(literal); 4401 Push(literal);
4361 // The literal index is on the stack, too. 4402 // The literal index is on the stack, too.
4362 Push(Add<HConstant>(expr->literal_index())); 4403 Push(Add<HConstant>(expr->literal_index()));
4363 4404
4364 HInstruction* elements = NULL; 4405 HInstruction* elements = NULL;
4365 4406
4366 for (int i = 0; i < length; i++) { 4407 for (int i = 0; i < length; i++) {
4367 Expression* subexpr = subexprs->at(i); 4408 Expression* subexpr = subexprs->at(i);
4368 // If the subexpression is a literal or a simple materialized literal it 4409 // If the subexpression is a literal or a simple materialized literal it
4369 // is already set in the cloned array. 4410 // is already set in the cloned array.
4370 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 4411 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
4371 4412
4372 CHECK_ALIVE(VisitForValue(subexpr)); 4413 CHECK_ALIVE(VisitForValue(subexpr));
4373 HValue* value = Pop(); 4414 HValue* value = Pop();
4374 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); 4415 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
4375 4416
4376 elements = AddLoadElements(literal, type_check); 4417 elements = AddLoadElements(literal);
4377 4418
4378 HValue* key = Add<HConstant>(i); 4419 HValue* key = Add<HConstant>(i);
4379 4420
4380 switch (boilerplate_elements_kind) { 4421 switch (boilerplate_elements_kind) {
4381 case FAST_SMI_ELEMENTS: 4422 case FAST_SMI_ELEMENTS:
4382 case FAST_HOLEY_SMI_ELEMENTS: 4423 case FAST_HOLEY_SMI_ELEMENTS:
4383 case FAST_ELEMENTS: 4424 case FAST_ELEMENTS:
4384 case FAST_HOLEY_ELEMENTS: 4425 case FAST_HOLEY_ELEMENTS:
4385 case FAST_DOUBLE_ELEMENTS: 4426 case FAST_DOUBLE_ELEMENTS:
4386 case FAST_HOLEY_DOUBLE_ELEMENTS: { 4427 case FAST_HOLEY_DOUBLE_ELEMENTS: {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
4428 4469
4429 4470
4430 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, 4471 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
4431 Handle<Map> map) { 4472 Handle<Map> map) {
4432 BuildCheckHeapObject(object); 4473 BuildCheckHeapObject(object);
4433 return Add<HCheckMaps>(object, map, top_info()); 4474 return Add<HCheckMaps>(object, map, top_info());
4434 } 4475 }
4435 4476
4436 4477
4437 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( 4478 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
4438 HValue* object, 4479 HValue* checked_object,
4439 Handle<String> name, 4480 Handle<String> name,
4440 HValue* value, 4481 HValue* value,
4441 Handle<Map> map, 4482 Handle<Map> map,
4442 LookupResult* lookup) { 4483 LookupResult* lookup) {
4443 ASSERT(lookup->IsFound()); 4484 ASSERT(lookup->IsFound());
4444 // If the property does not exist yet, we have to check that it wasn't made 4485 // If the property does not exist yet, we have to check that it wasn't made
4445 // readonly or turned into a setter by some meanwhile modifications on the 4486 // readonly or turned into a setter by some meanwhile modifications on the
4446 // prototype chain. 4487 // prototype chain.
4447 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { 4488 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) {
4448 Object* proto = map->prototype(); 4489 Object* proto = map->prototype();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4480 if (transition_to_field) { 4521 if (transition_to_field) {
4481 // The store requires a mutable HeapNumber to be allocated. 4522 // The store requires a mutable HeapNumber to be allocated.
4482 NoObservableSideEffectsScope no_side_effects(this); 4523 NoObservableSideEffectsScope no_side_effects(this);
4483 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); 4524 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
4484 HInstruction* heap_number = Add<HAllocate>(heap_number_size, 4525 HInstruction* heap_number = Add<HAllocate>(heap_number_size,
4485 HType::HeapNumber(), isolate()->heap()->GetPretenureMode(), 4526 HType::HeapNumber(), isolate()->heap()->GetPretenureMode(),
4486 HEAP_NUMBER_TYPE); 4527 HEAP_NUMBER_TYPE);
4487 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); 4528 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map());
4488 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), 4529 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
4489 value); 4530 value);
4490 instr = New<HStoreNamedField>(object, heap_number_access, 4531 instr = New<HStoreNamedField>(checked_object->ActualValue(),
4491 heap_number); 4532 heap_number_access,
4533 heap_number);
4492 } else { 4534 } else {
4493 // Already holds a HeapNumber; load the box and write its value field. 4535 // Already holds a HeapNumber; load the box and write its value field.
4494 HInstruction* heap_number = Add<HLoadNamedField>(object, 4536 HInstruction* heap_number = Add<HLoadNamedField>(checked_object,
4495 heap_number_access); 4537 heap_number_access);
4496 heap_number->set_type(HType::HeapNumber()); 4538 heap_number->set_type(HType::HeapNumber());
4497 instr = New<HStoreNamedField>(heap_number, 4539 instr = New<HStoreNamedField>(heap_number,
4498 HObjectAccess::ForHeapNumberValue(), 4540 HObjectAccess::ForHeapNumberValue(),
4499 value); 4541 value);
4500 } 4542 }
4501 } else { 4543 } else {
4502 // This is a normal store. 4544 // This is a normal store.
4503 instr = New<HStoreNamedField>(object, field_access, value); 4545 instr = New<HStoreNamedField>(checked_object->ActualValue(),
4546 field_access,
4547 value);
4504 } 4548 }
4505 4549
4506 if (transition_to_field) { 4550 if (transition_to_field) {
4507 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); 4551 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
4508 HConstant* transition_constant = Add<HConstant>(transition); 4552 HConstant* transition_constant = Add<HConstant>(transition);
4509 instr->SetTransition(transition_constant, top_info()); 4553 instr->SetTransition(transition_constant, top_info());
4510 // TODO(fschneider): Record the new map type of the object in the IR to 4554 // TODO(fschneider): Record the new map type of the object in the IR to
4511 // enable elimination of redundant checks after the transition store. 4555 // enable elimination of redundant checks after the transition store.
4512 instr->SetGVNFlag(kChangesMaps); 4556 instr->SetGVNFlag(kChangesMaps);
4513 } 4557 }
(...skipping 16 matching lines...) Expand all
4530 4574
4531 4575
4532 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( 4576 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
4533 HValue* object, 4577 HValue* object,
4534 Handle<String> name, 4578 Handle<String> name,
4535 HValue* value, 4579 HValue* value,
4536 Handle<Map> map) { 4580 Handle<Map> map) {
4537 // Handle a store to a known field. 4581 // Handle a store to a known field.
4538 LookupResult lookup(isolate()); 4582 LookupResult lookup(isolate());
4539 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4583 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4540 AddCheckMap(object, map); 4584 HCheckMaps* checked_object = AddCheckMap(object, map);
4541 return BuildStoreNamedField(object, name, value, map, &lookup); 4585 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
4542 } 4586 }
4543 4587
4544 // No luck, do a generic store. 4588 // No luck, do a generic store.
4545 return BuildStoreNamedGeneric(object, name, value); 4589 return BuildStoreNamedGeneric(object, name, value);
4546 } 4590 }
4547 4591
4548 4592
4549 static bool CanLoadPropertyFromPrototype(Handle<Map> map, 4593 static bool CanLoadPropertyFromPrototype(Handle<Map> map,
4550 Handle<Name> name, 4594 Handle<Name> name,
4551 LookupResult* lookup) { 4595 LookupResult* lookup) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
4589 // In-objectness did not match. 4633 // In-objectness did not match.
4590 break; 4634 break;
4591 } 4635 }
4592 access = access.WithRepresentation( 4636 access = access.WithRepresentation(
4593 access.representation().generalize(new_access.representation())); 4637 access.representation().generalize(new_access.representation()));
4594 } 4638 }
4595 4639
4596 if (count == types->length()) { 4640 if (count == types->length()) {
4597 // Everything matched; can use monomorphic load. 4641 // Everything matched; can use monomorphic load.
4598 BuildCheckHeapObject(object); 4642 BuildCheckHeapObject(object);
4599 HCheckMaps* type_check = Add<HCheckMaps>(object, types); 4643 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
4600 return BuildLoadNamedField(object, access, type_check); 4644 return BuildLoadNamedField(checked_object, access);
4601 } 4645 }
4602 4646
4603 if (count != 0) return NULL; 4647 if (count != 0) return NULL;
4604 4648
4605 // Second chance: the property is on the prototype and all maps have the 4649 // Second chance: the property is on the prototype and all maps have the
4606 // same prototype. 4650 // same prototype.
4607 Handle<Map> map(types->at(0)); 4651 Handle<Map> map(types->at(0));
4608 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; 4652 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL;
4609 4653
4610 Handle<Object> prototype(map->prototype(), isolate()); 4654 Handle<Object> prototype(map->prototype(), isolate());
4611 for (count = 1; count < types->length(); ++count) { 4655 for (count = 1; count < types->length(); ++count) {
4612 Handle<Map> test_map(types->at(count)); 4656 Handle<Map> test_map(types->at(count));
4613 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; 4657 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL;
4614 if (test_map->prototype() != *prototype) return NULL; 4658 if (test_map->prototype() != *prototype) return NULL;
4615 } 4659 }
4616 4660
4617 LookupInPrototypes(map, name, &lookup); 4661 LookupInPrototypes(map, name, &lookup);
4618 if (!lookup.IsField()) return NULL; 4662 if (!lookup.IsField()) return NULL;
4619 4663
4620 BuildCheckHeapObject(object); 4664 BuildCheckHeapObject(object);
4621 HCheckMaps* type_check = Add<HCheckMaps>(object, types); 4665 Add<HCheckMaps>(object, types);
4622 4666
4623 Handle<JSObject> holder(lookup.holder()); 4667 Handle<JSObject> holder(lookup.holder());
4624 Handle<Map> holder_map(holder->map()); 4668 Handle<Map> holder_map(holder->map());
4625 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); 4669 HValue* checked_holder = BuildCheckPrototypeMaps(
4626 HValue* holder_value = Add<HConstant>(holder); 4670 Handle<JSObject>::cast(prototype), holder);
4627 return BuildLoadNamedField(holder_value, 4671 return BuildLoadNamedField(checked_holder,
4628 HObjectAccess::ForField(holder_map, &lookup, name), type_check); 4672 HObjectAccess::ForField(holder_map, &lookup, name));
4629 } 4673 }
4630 4674
4631 4675
4632 // Returns true if an instance of this map can never find a property with this 4676 // Returns true if an instance of this map can never find a property with this
4633 // name in its prototype chain. This means all prototypes up to the top are 4677 // name in its prototype chain. This means all prototypes up to the top are
4634 // fast and don't have the name in them. It would be good if we could optimize 4678 // fast and don't have the name in them. It would be good if we could optimize
4635 // polymorphic loads where the property is sometimes found in the prototype 4679 // polymorphic loads where the property is sometimes found in the prototype
4636 // chain. 4680 // chain.
4637 static bool PrototypeChainCanNeverResolve( 4681 static bool PrototypeChainCanNeverResolve(
4638 Handle<Map> map, Handle<String> name) { 4682 Handle<Map> map, Handle<String> name) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
4693 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4737 HBasicBlock* if_false = graph()->CreateBasicBlock();
4694 HCompareMap* compare = 4738 HCompareMap* compare =
4695 new(zone()) HCompareMap(object, map, if_true, if_false); 4739 new(zone()) HCompareMap(object, map, if_true, if_false);
4696 current_block()->Finish(compare); 4740 current_block()->Finish(compare);
4697 4741
4698 set_current_block(if_true); 4742 set_current_block(if_true);
4699 4743
4700 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. 4744 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
4701 if (lookup.IsField()) { 4745 if (lookup.IsField()) {
4702 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); 4746 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
4703 HLoadNamedField* load = BuildLoadNamedField(object, access, compare); 4747 HLoadNamedField* load = BuildLoadNamedField(compare, access);
4704 load->set_position(expr->position()); 4748 load->set_position(expr->position());
4705 AddInstruction(load); 4749 AddInstruction(load);
4706 if (!ast_context()->IsEffect()) Push(load); 4750 if (!ast_context()->IsEffect()) Push(load);
4707 } else if (lookup.IsConstant()) { 4751 } else if (lookup.IsConstant()) {
4708 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); 4752 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
4709 HConstant* hconstant = Add<HConstant>(constant); 4753 HConstant* hconstant = Add<HConstant>(constant);
4710 if (!ast_context()->IsEffect()) Push(hconstant); 4754 if (!ast_context()->IsEffect()) Push(hconstant);
4711 } else { 4755 } else {
4712 ASSERT(!lookup.IsFound()); 4756 ASSERT(!lookup.IsFound());
4713 if (map->prototype()->IsJSObject()) { 4757 if (map->prototype()->IsJSObject()) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
4793 } else if (access.IsInobject() != new_access.IsInobject()) { 4837 } else if (access.IsInobject() != new_access.IsInobject()) {
4794 // In-objectness did not match. 4838 // In-objectness did not match.
4795 break; 4839 break;
4796 } 4840 }
4797 } 4841 }
4798 4842
4799 if (count != types->length()) return false; 4843 if (count != types->length()) return false;
4800 4844
4801 // Everything matched; can use monomorphic store. 4845 // Everything matched; can use monomorphic store.
4802 BuildCheckHeapObject(object); 4846 BuildCheckHeapObject(object);
4803 Add<HCheckMaps>(object, types); 4847 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
4804 HInstruction* store; 4848 HInstruction* store;
4805 CHECK_ALIVE_OR_RETURN( 4849 CHECK_ALIVE_OR_RETURN(
4806 store = BuildStoreNamedField( 4850 store = BuildStoreNamedField(
4807 object, name, store_value, types->at(count - 1), &lookup), 4851 checked_object, name, store_value, types->at(count - 1), &lookup),
4808 true); 4852 true);
4809 if (!ast_context()->IsEffect()) Push(result_value); 4853 if (!ast_context()->IsEffect()) Push(result_value);
4810 store->set_position(position); 4854 store->set_position(position);
4811 AddInstruction(store); 4855 AddInstruction(store);
4812 Add<HSimulate>(assignment_id); 4856 Add<HSimulate>(assignment_id);
4813 if (!ast_context()->IsEffect()) Drop(1); 4857 if (!ast_context()->IsEffect()) Drop(1);
4814 ast_context()->ReturnValue(result_value); 4858 ast_context()->ReturnValue(result_value);
4815 return true; 4859 return true;
4816 } 4860 }
4817 4861
(...skipping 28 matching lines...) Expand all
4846 ++count; 4890 ++count;
4847 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4891 HBasicBlock* if_true = graph()->CreateBasicBlock();
4848 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4892 HBasicBlock* if_false = graph()->CreateBasicBlock();
4849 HCompareMap* compare = 4893 HCompareMap* compare =
4850 new(zone()) HCompareMap(object, map, if_true, if_false); 4894 new(zone()) HCompareMap(object, map, if_true, if_false);
4851 current_block()->Finish(compare); 4895 current_block()->Finish(compare);
4852 4896
4853 set_current_block(if_true); 4897 set_current_block(if_true);
4854 HInstruction* instr; 4898 HInstruction* instr;
4855 CHECK_ALIVE(instr = BuildStoreNamedField( 4899 CHECK_ALIVE(instr = BuildStoreNamedField(
4856 object, name, store_value, map, &lookup)); 4900 compare, name, store_value, map, &lookup));
4857 instr->set_position(position); 4901 instr->set_position(position);
4858 // Goto will add the HSimulate for the store. 4902 // Goto will add the HSimulate for the store.
4859 AddInstruction(instr); 4903 AddInstruction(instr);
4860 if (!ast_context()->IsEffect()) Push(result_value); 4904 if (!ast_context()->IsEffect()) Push(result_value);
4861 current_block()->Goto(join); 4905 current_block()->Goto(join);
4862 4906
4863 set_current_block(if_false); 4907 set_current_block(if_false);
4864 } 4908 }
4865 } 4909 }
4866 4910
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
5366 HValue* value = environment()->Pop(); 5410 HValue* value = environment()->Pop();
5367 HThrow* instr = Add<HThrow>(value); 5411 HThrow* instr = Add<HThrow>(value);
5368 instr->set_position(expr->position()); 5412 instr->set_position(expr->position());
5369 Add<HSimulate>(expr->id()); 5413 Add<HSimulate>(expr->id());
5370 current_block()->FinishExit(new(zone()) HAbnormalExit); 5414 current_block()->FinishExit(new(zone()) HAbnormalExit);
5371 set_current_block(NULL); 5415 set_current_block(NULL);
5372 } 5416 }
5373 5417
5374 5418
5375 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 5419 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
5376 HObjectAccess access, 5420 HObjectAccess access) {
5377 HValue* typecheck) {
5378 if (FLAG_track_double_fields && access.representation().IsDouble()) { 5421 if (FLAG_track_double_fields && access.representation().IsDouble()) {
5379 // load the heap number 5422 // load the heap number
5380 HLoadNamedField* heap_number = Add<HLoadNamedField>( 5423 HLoadNamedField* heap_number = Add<HLoadNamedField>(
5381 object, access.WithRepresentation(Representation::Tagged())); 5424 object, access.WithRepresentation(Representation::Tagged()));
5382 heap_number->set_type(HType::HeapNumber()); 5425 heap_number->set_type(HType::HeapNumber());
5383 // load the double value from it 5426 // load the double value from it
5384 return New<HLoadNamedField>(heap_number, 5427 return New<HLoadNamedField>(
5385 HObjectAccess::ForHeapNumberValue(), 5428 heap_number, HObjectAccess::ForHeapNumberValue());
5386 typecheck);
5387 } 5429 }
5388 return New<HLoadNamedField>(object, access, typecheck); 5430 return New<HLoadNamedField>(object, access);
5389 } 5431 }
5390 5432
5391 5433
5392 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, 5434 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
5393 HValue* typecheck) { 5435 HValue* checked_string) {
5394 if (FLAG_fold_constants && object->IsConstant()) { 5436 if (FLAG_fold_constants && object->IsConstant()) {
5395 HConstant* constant = HConstant::cast(object); 5437 HConstant* constant = HConstant::cast(object);
5396 if (constant->HasStringValue()) { 5438 if (constant->HasStringValue()) {
5397 return New<HConstant>(constant->StringValue()->length()); 5439 return New<HConstant>(constant->StringValue()->length());
5398 } 5440 }
5399 } 5441 }
5400 return BuildLoadNamedField( 5442 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength());
5401 object, HObjectAccess::ForStringLength(), typecheck);
5402 } 5443 }
5403 5444
5404 5445
5405 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 5446 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
5406 HValue* object, 5447 HValue* object,
5407 Handle<String> name, 5448 Handle<String> name,
5408 Property* expr) { 5449 Property* expr) {
5409 if (expr->IsUninitialized()) { 5450 if (expr->IsUninitialized()) {
5410 Add<HDeoptimize>("Insufficient feedback for generic named load", 5451 Add<HDeoptimize>("Insufficient feedback for generic named load",
5411 Deoptimizer::SOFT); 5452 Deoptimizer::SOFT);
(...skipping 18 matching lines...) Expand all
5430 HValue* object, 5471 HValue* object,
5431 Handle<String> name, 5472 Handle<String> name,
5432 Property* expr, 5473 Property* expr,
5433 Handle<Map> map) { 5474 Handle<Map> map) {
5434 // Handle a load from a known field. 5475 // Handle a load from a known field.
5435 ASSERT(!map->is_dictionary_map()); 5476 ASSERT(!map->is_dictionary_map());
5436 5477
5437 // Handle access to various length properties 5478 // Handle access to various length properties
5438 if (name->Equals(isolate()->heap()->length_string())) { 5479 if (name->Equals(isolate()->heap()->length_string())) {
5439 if (map->instance_type() == JS_ARRAY_TYPE) { 5480 if (map->instance_type() == JS_ARRAY_TYPE) {
5440 HCheckMaps* type_check = AddCheckMap(object, map); 5481 HCheckMaps* checked_object = AddCheckMap(object, map);
5441 return New<HLoadNamedField>(object, 5482 return New<HLoadNamedField>(
5442 HObjectAccess::ForArrayLength(map->elements_kind()), type_check); 5483 checked_object, HObjectAccess::ForArrayLength(map->elements_kind()));
5443 } 5484 }
5444 } 5485 }
5445 5486
5446 LookupResult lookup(isolate()); 5487 LookupResult lookup(isolate());
5447 map->LookupDescriptor(NULL, *name, &lookup); 5488 map->LookupDescriptor(NULL, *name, &lookup);
5448 if (lookup.IsField()) { 5489 if (lookup.IsField()) {
5449 HCheckMaps* type_check = AddCheckMap(object, map); 5490 HCheckMaps* checked_object = AddCheckMap(object, map);
5450 return BuildLoadNamedField(object, 5491 return BuildLoadNamedField(
5451 HObjectAccess::ForField(map, &lookup, name), type_check); 5492 checked_object, HObjectAccess::ForField(map, &lookup, name));
5452 } 5493 }
5453 5494
5454 // Handle a load of a constant known function. 5495 // Handle a load of a constant known function.
5455 if (lookup.IsConstant()) { 5496 if (lookup.IsConstant()) {
5456 AddCheckMap(object, map); 5497 AddCheckMap(object, map);
5457 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); 5498 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
5458 return New<HConstant>(constant); 5499 return New<HConstant>(constant);
5459 } 5500 }
5460 5501
5461 // Handle a load from a known field somewhere in the prototype chain. 5502 // Handle a load from a known field somewhere in the prototype chain.
5462 LookupInPrototypes(map, name, &lookup); 5503 LookupInPrototypes(map, name, &lookup);
5463 if (lookup.IsField()) { 5504 if (lookup.IsField()) {
5464 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5505 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5465 Handle<JSObject> holder(lookup.holder()); 5506 Handle<JSObject> holder(lookup.holder());
5466 Handle<Map> holder_map(holder->map()); 5507 Handle<Map> holder_map(holder->map());
5467 HCheckMaps* type_check = AddCheckMap(object, map); 5508 AddCheckMap(object, map);
5468 BuildCheckPrototypeMaps(prototype, holder); 5509 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder);
5469 HValue* holder_value = Add<HConstant>(holder); 5510 return BuildLoadNamedField(
5470 return BuildLoadNamedField(holder_value, 5511 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name));
5471 HObjectAccess::ForField(holder_map, &lookup, name), type_check);
5472 } 5512 }
5473 5513
5474 // Handle a load of a constant function somewhere in the prototype chain. 5514 // Handle a load of a constant function somewhere in the prototype chain.
5475 if (lookup.IsConstant()) { 5515 if (lookup.IsConstant()) {
5476 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5516 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5477 Handle<JSObject> holder(lookup.holder()); 5517 Handle<JSObject> holder(lookup.holder());
5478 Handle<Map> holder_map(holder->map()); 5518 Handle<Map> holder_map(holder->map());
5479 AddCheckMap(object, map); 5519 AddCheckMap(object, map);
5480 BuildCheckPrototypeMaps(prototype, holder); 5520 BuildCheckPrototypeMaps(prototype, holder);
5481 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); 5521 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
5482 return New<HConstant>(constant); 5522 return New<HConstant>(constant);
5483 } 5523 }
5484 5524
5485 // No luck, do a generic load. 5525 // No luck, do a generic load.
5486 return BuildLoadNamedGeneric(object, name, expr); 5526 return BuildLoadNamedGeneric(object, name, expr);
5487 } 5527 }
5488 5528
5489 5529
5490 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5530 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
5491 HValue* key) { 5531 HValue* key) {
5492 HValue* context = environment()->context(); 5532 HValue* context = environment()->context();
5493 return new(zone()) HLoadKeyedGeneric(context, object, key); 5533 return new(zone()) HLoadKeyedGeneric(context, object, key);
5494 } 5534 }
5495 5535
5496 5536
5497 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( 5537 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
5498 HValue* object,
5499 HValue* key,
5500 HValue* val,
5501 HValue* dependency,
5502 Handle<Map> map,
5503 bool is_store,
5504 KeyedAccessStoreMode store_mode) {
5505 HCheckMaps* mapcheck = Add<HCheckMaps>(object, map, top_info(), dependency);
5506 if (dependency) {
5507 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
5508 }
5509
5510 // Loads from a "stock" fast holey double arrays can elide the hole check. 5538 // Loads from a "stock" fast holey double arrays can elide the hole check.
5511 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5539 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
5512 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 5540 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
5513 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 5541 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
5514 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 5542 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
5515 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 5543 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
5516 BuildCheckPrototypeMaps(prototype, object_prototype); 5544 BuildCheckPrototypeMaps(prototype, object_prototype);
5517 load_mode = ALLOW_RETURN_HOLE; 5545 load_mode = ALLOW_RETURN_HOLE;
5518 graph()->MarkDependsOnEmptyArrayProtoElements(); 5546 graph()->MarkDependsOnEmptyArrayProtoElements();
5519 } 5547 }
5520 5548
5521 return BuildUncheckedMonomorphicElementAccess( 5549 return load_mode;
5522 object, key, val,
5523 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
5524 map->elements_kind(), is_store, load_mode, store_mode);
5525 } 5550 }
5526 5551
5527 5552
5553 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
5554 HValue* object,
5555 HValue* key,
5556 HValue* val,
5557 HValue* dependency,
5558 Handle<Map> map,
5559 bool is_store,
5560 KeyedAccessStoreMode store_mode) {
5561 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
5562 dependency);
5563 if (dependency) {
5564 checked_object->ClearGVNFlag(kDependsOnElementsKind);
5565 }
5566
5567 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
5568 return BuildUncheckedMonomorphicElementAccess(
5569 checked_object, key, val,
5570 map->instance_type() == JS_ARRAY_TYPE,
5571 map->elements_kind(), is_store,
5572 load_mode, store_mode);
5573 }
5574
5575
5528 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( 5576 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
5529 HValue* object, 5577 HValue* object,
5530 HValue* key, 5578 HValue* key,
5531 HValue* val, 5579 HValue* val,
5532 SmallMapList* maps) { 5580 SmallMapList* maps) {
5533 // For polymorphic loads of similar elements kinds (i.e. all tagged or all 5581 // For polymorphic loads of similar elements kinds (i.e. all tagged or all
5534 // double), always use the "worst case" code without a transition. This is 5582 // double), always use the "worst case" code without a transition. This is
5535 // much faster than transitioning the elements to the worst case, trading a 5583 // much faster than transitioning the elements to the worst case, trading a
5536 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. 5584 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
5537 bool has_double_maps = false; 5585 bool has_double_maps = false;
5538 bool has_smi_or_object_maps = false; 5586 bool has_smi_or_object_maps = false;
5539 bool has_js_array_access = false; 5587 bool has_js_array_access = false;
5540 bool has_non_js_array_access = false; 5588 bool has_non_js_array_access = false;
5589 bool has_seen_holey_elements = false;
5541 Handle<Map> most_general_consolidated_map; 5590 Handle<Map> most_general_consolidated_map;
5542 for (int i = 0; i < maps->length(); ++i) { 5591 for (int i = 0; i < maps->length(); ++i) {
5543 Handle<Map> map = maps->at(i); 5592 Handle<Map> map = maps->at(i);
5544 // Don't allow mixing of JSArrays with JSObjects. 5593 // Don't allow mixing of JSArrays with JSObjects.
5545 if (map->instance_type() == JS_ARRAY_TYPE) { 5594 if (map->instance_type() == JS_ARRAY_TYPE) {
5546 if (has_non_js_array_access) return NULL; 5595 if (has_non_js_array_access) return NULL;
5547 has_js_array_access = true; 5596 has_js_array_access = true;
5548 } else if (has_js_array_access) { 5597 } else if (has_js_array_access) {
5549 return NULL; 5598 return NULL;
5550 } else { 5599 } else {
5551 has_non_js_array_access = true; 5600 has_non_js_array_access = true;
5552 } 5601 }
5553 // Don't allow mixed, incompatible elements kinds. 5602 // Don't allow mixed, incompatible elements kinds.
5554 if (map->has_fast_double_elements()) { 5603 if (map->has_fast_double_elements()) {
5555 if (has_smi_or_object_maps) return NULL; 5604 if (has_smi_or_object_maps) return NULL;
5556 has_double_maps = true; 5605 has_double_maps = true;
5557 } else if (map->has_fast_smi_or_object_elements()) { 5606 } else if (map->has_fast_smi_or_object_elements()) {
5558 if (has_double_maps) return NULL; 5607 if (has_double_maps) return NULL;
5559 has_smi_or_object_maps = true; 5608 has_smi_or_object_maps = true;
5560 } else { 5609 } else {
5561 return NULL; 5610 return NULL;
5562 } 5611 }
5612 // Remember if we've ever seen holey elements.
5613 if (IsHoleyElementsKind(map->elements_kind())) {
5614 has_seen_holey_elements = true;
5615 }
5563 // Remember the most general elements kind, the code for its load will 5616 // Remember the most general elements kind, the code for its load will
5564 // properly handle all of the more specific cases. 5617 // properly handle all of the more specific cases.
5565 if ((i == 0) || IsMoreGeneralElementsKindTransition( 5618 if ((i == 0) || IsMoreGeneralElementsKindTransition(
5566 most_general_consolidated_map->elements_kind(), 5619 most_general_consolidated_map->elements_kind(),
5567 map->elements_kind())) { 5620 map->elements_kind())) {
5568 most_general_consolidated_map = map; 5621 most_general_consolidated_map = map;
5569 } 5622 }
5570 } 5623 }
5571 if (!has_double_maps && !has_smi_or_object_maps) return NULL; 5624 if (!has_double_maps && !has_smi_or_object_maps) return NULL;
5572 5625
5573 HCheckMaps* check_maps = Add<HCheckMaps>(object, maps); 5626 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
5627 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
5628 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
5629 ElementsKind consolidated_elements_kind = has_seen_holey_elements
5630 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
5631 : most_general_consolidated_map->elements_kind();
5574 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 5632 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
5575 object, key, val, check_maps, 5633 checked_object, key, val,
5576 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 5634 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
5577 most_general_consolidated_map->elements_kind(), 5635 consolidated_elements_kind,
5578 false, NEVER_RETURN_HOLE, STANDARD_STORE); 5636 false, NEVER_RETURN_HOLE, STANDARD_STORE);
5579 return instr; 5637 return instr;
5580 } 5638 }
5581 5639
5582 5640
5583 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 5641 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
5584 HValue* object, 5642 HValue* object,
5585 HValue* key, 5643 HValue* key,
5586 HValue* val, 5644 HValue* val,
5587 Expression* prop, 5645 Expression* prop,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
5654 } else { 5712 } else {
5655 instr = BuildMonomorphicElementAccess( 5713 instr = BuildMonomorphicElementAccess(
5656 object, key, val, transition, untransitionable_map, is_store, 5714 object, key, val, transition, untransitionable_map, is_store,
5657 store_mode); 5715 store_mode);
5658 } 5716 }
5659 *has_side_effects |= instr->HasObservableSideEffects(); 5717 *has_side_effects |= instr->HasObservableSideEffects();
5660 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5718 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5661 return is_store ? NULL : instr; 5719 return is_store ? NULL : instr;
5662 } 5720 }
5663 5721
5664 HInstruction* checkspec =
5665 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
5666 HBasicBlock* join = graph()->CreateBasicBlock(); 5722 HBasicBlock* join = graph()->CreateBasicBlock();
5667 5723
5668 HInstruction* elements = AddLoadElements(object, checkspec);
5669
5670 for (int i = 0; i < untransitionable_maps.length(); ++i) { 5724 for (int i = 0; i < untransitionable_maps.length(); ++i) {
5671 Handle<Map> map = untransitionable_maps[i]; 5725 Handle<Map> map = untransitionable_maps[i];
5672 ElementsKind elements_kind = map->elements_kind(); 5726 ElementsKind elements_kind = map->elements_kind();
5673 HBasicBlock* this_map = graph()->CreateBasicBlock(); 5727 HBasicBlock* this_map = graph()->CreateBasicBlock();
5674 HBasicBlock* other_map = graph()->CreateBasicBlock(); 5728 HBasicBlock* other_map = graph()->CreateBasicBlock();
5675 HCompareMap* mapcompare = 5729 HCompareMap* mapcompare =
5676 new(zone()) HCompareMap(object, map, this_map, other_map); 5730 new(zone()) HCompareMap(object, map, this_map, other_map);
5677 current_block()->Finish(mapcompare); 5731 current_block()->Finish(mapcompare);
5678 5732
5679 set_current_block(this_map); 5733 set_current_block(this_map);
5680 HInstruction* checked_key = NULL;
5681 HInstruction* access = NULL; 5734 HInstruction* access = NULL;
5682 if (IsFastElementsKind(elements_kind)) { 5735 if (IsDictionaryElementsKind(elements_kind)) {
5683 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { 5736 access = is_store
5684 Add<HCheckMaps>( 5737 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
5685 elements, isolate()->factory()->fixed_array_map(), 5738 : AddInstruction(BuildLoadKeyedGeneric(object, key));
5686 top_info(), mapcompare);
5687 }
5688 if (map->instance_type() == JS_ARRAY_TYPE) {
5689 HInstruction* length = Add<HLoadNamedField>(
5690 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare);
5691 checked_key = Add<HBoundsCheck>(key, length);
5692 } else {
5693 HInstruction* length = AddLoadFixedArrayLength(elements);
5694 checked_key = Add<HBoundsCheck>(key, length);
5695 }
5696 access = AddFastElementAccess(
5697 elements, checked_key, val, mapcompare,
5698 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE);
5699 } else if (IsDictionaryElementsKind(elements_kind)) {
5700 if (is_store) {
5701 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
5702 } else {
5703 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
5704 }
5705 } else { 5739 } else {
5706 ASSERT(IsExternalArrayElementsKind(elements_kind)); 5740 ASSERT(IsFastElementsKind(elements_kind) ||
5707 HInstruction* length = AddLoadFixedArrayLength(elements); 5741 IsExternalArrayElementsKind(elements_kind));
5708 checked_key = Add<HBoundsCheck>(key, length); 5742 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
5709 HLoadExternalArrayPointer* external_elements = 5743 // Happily, mapcompare is a checked object.
5710 Add<HLoadExternalArrayPointer>(elements); 5744 access = BuildUncheckedMonomorphicElementAccess(
5711 access = AddExternalArrayElementAccess( 5745 mapcompare, key, val,
5712 external_elements, checked_key, val, 5746 map->instance_type() == JS_ARRAY_TYPE,
5713 mapcompare, elements_kind, is_store); 5747 elements_kind, is_store,
5748 load_mode,
5749 store_mode);
5714 } 5750 }
5715 *has_side_effects |= access->HasObservableSideEffects(); 5751 *has_side_effects |= access->HasObservableSideEffects();
5716 // The caller will use has_side_effects and add a correct Simulate. 5752 // The caller will use has_side_effects and add a correct Simulate.
5717 access->SetFlag(HValue::kHasNoObservableSideEffects); 5753 access->SetFlag(HValue::kHasNoObservableSideEffects);
5718 if (position != RelocInfo::kNoPosition) access->set_position(position); 5754 if (position != RelocInfo::kNoPosition) access->set_position(position);
5719 if (!is_store) { 5755 if (!is_store) {
5720 Push(access); 5756 Push(access);
5721 } 5757 }
5722 NoObservableSideEffectsScope scope(this); 5758 NoObservableSideEffectsScope scope(this);
5723 current_block()->GotoNoSimulate(join); 5759 current_block()->GotoNoSimulate(join);
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
5956 Drop(1); 5992 Drop(1);
5957 } 5993 }
5958 } 5994 }
5959 return ast_context()->ReturnValue(load); 5995 return ast_context()->ReturnValue(load);
5960 } 5996 }
5961 instr->set_position(expr->position()); 5997 instr->set_position(expr->position());
5962 return ast_context()->ReturnInstruction(instr, expr->id()); 5998 return ast_context()->ReturnInstruction(instr, expr->id());
5963 } 5999 }
5964 6000
5965 6001
5966 void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, 6002 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
5967 CompilationInfo* info) { 6003 CompilationInfo* info) {
5968 HConstant* constant_value = New<HConstant>(constant); 6004 HConstant* constant_value = New<HConstant>(constant);
5969 6005
5970 if (constant->map()->CanOmitMapChecks()) { 6006 if (constant->map()->CanOmitMapChecks()) {
5971 constant->map()->AddDependentCompilationInfo( 6007 constant->map()->AddDependentCompilationInfo(
5972 DependentCode::kPrototypeCheckGroup, info); 6008 DependentCode::kPrototypeCheckGroup, info);
5973 return; 6009 return constant_value;
5974 } 6010 }
5975 6011
5976 AddInstruction(constant_value); 6012 AddInstruction(constant_value);
5977 HCheckMaps* check = 6013 HCheckMaps* check =
5978 Add<HCheckMaps>(constant_value, handle(constant->map()), info); 6014 Add<HCheckMaps>(constant_value, handle(constant->map()), info);
5979 check->ClearGVNFlag(kDependsOnElementsKind); 6015 check->ClearGVNFlag(kDependsOnElementsKind);
6016 return check;
5980 } 6017 }
5981 6018
5982 6019
5983 void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, 6020 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
5984 Handle<JSObject> holder) { 6021 Handle<JSObject> holder) {
5985 BuildConstantMapCheck(prototype, top_info());
5986 while (!prototype.is_identical_to(holder)) { 6022 while (!prototype.is_identical_to(holder)) {
6023 BuildConstantMapCheck(prototype, top_info());
5987 prototype = handle(JSObject::cast(prototype->GetPrototype())); 6024 prototype = handle(JSObject::cast(prototype->GetPrototype()));
5988 BuildConstantMapCheck(prototype, top_info());
5989 } 6025 }
6026
6027 HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info());
6028 if (!checked_object->IsLinked()) AddInstruction(checked_object);
6029 return checked_object;
5990 } 6030 }
5991 6031
5992 6032
5993 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, 6033 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
5994 Handle<Map> receiver_map) { 6034 Handle<Map> receiver_map) {
5995 if (!holder.is_null()) { 6035 if (!holder.is_null()) {
5996 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 6036 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
5997 BuildCheckPrototypeMaps(prototype, holder); 6037 BuildCheckPrototypeMaps(prototype, holder);
5998 } 6038 }
5999 } 6039 }
(...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after
6805 HInstruction* sqrt = 6845 HInstruction* sqrt =
6806 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); 6846 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
6807 AddInstruction(sqrt); 6847 AddInstruction(sqrt);
6808 // MathPowHalf doesn't have side effects so there's no need for 6848 // MathPowHalf doesn't have side effects so there's no need for
6809 // an environment simulation here. 6849 // an environment simulation here.
6810 ASSERT(!sqrt->HasObservableSideEffects()); 6850 ASSERT(!sqrt->HasObservableSideEffects());
6811 result = HDiv::New(zone(), context, one, sqrt); 6851 result = HDiv::New(zone(), context, one, sqrt);
6812 } else if (exponent == 2.0) { 6852 } else if (exponent == 2.0) {
6813 result = HMul::New(zone(), context, left, left); 6853 result = HMul::New(zone(), context, left, left);
6814 } 6854 }
6815 } else if (right->EqualsInteger32Constant(2)) {
6816 result = HMul::New(zone(), context, left, left);
6817 } 6855 }
6818 6856
6819 if (result == NULL) { 6857 if (result == NULL) {
6820 result = HPower::New(zone(), context, left, right); 6858 result = HPower::New(zone(), context, left, right);
6821 } 6859 }
6822 ast_context()->ReturnInstruction(result, expr->id()); 6860 ast_context()->ReturnInstruction(result, expr->id());
6823 return true; 6861 return true;
6824 } 6862 }
6825 break; 6863 break;
6826 case kMathRandom: 6864 case kMathRandom:
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after
7485 } 7523 }
7486 Push(number_input); 7524 Push(number_input);
7487 } 7525 }
7488 7526
7489 // The addition has no side effects, so we do not need 7527 // The addition has no side effects, so we do not need
7490 // to simulate the expression stack after this instruction. 7528 // to simulate the expression stack after this instruction.
7491 // Any later failures deopt to the load of the input or earlier. 7529 // Any later failures deopt to the load of the input or earlier.
7492 HConstant* delta = (expr->op() == Token::INC) 7530 HConstant* delta = (expr->op() == Token::INC)
7493 ? graph()->GetConstant1() 7531 ? graph()->GetConstant1()
7494 : graph()->GetConstantMinus1(); 7532 : graph()->GetConstantMinus1();
7495 HInstruction* instr = Add<HAdd>(Top(), delta); 7533 HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
7534 if (instr->IsAdd()) {
7535 HAdd* add = HAdd::cast(instr);
7536 add->set_observed_input_representation(1, rep);
7537 add->set_observed_input_representation(2, Representation::Smi());
7538 }
7496 instr->SetFlag(HInstruction::kCannotBeTagged); 7539 instr->SetFlag(HInstruction::kCannotBeTagged);
7497 instr->ClearAllSideEffects(); 7540 instr->ClearAllSideEffects();
7498 return instr; 7541 return instr;
7499 } 7542 }
7500 7543
7501 7544
7502 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { 7545 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
7503 ASSERT(!HasStackOverflow()); 7546 ASSERT(!HasStackOverflow());
7504 ASSERT(current_block() != NULL); 7547 ASSERT(current_block() != NULL);
7505 ASSERT(current_block()->HasPredecessor()); 7548 ASSERT(current_block()->HasPredecessor());
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
8197 8240
8198 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 8241 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
8199 Expression* sub_expr, 8242 Expression* sub_expr,
8200 NilValue nil) { 8243 NilValue nil) {
8201 ASSERT(!HasStackOverflow()); 8244 ASSERT(!HasStackOverflow());
8202 ASSERT(current_block() != NULL); 8245 ASSERT(current_block() != NULL);
8203 ASSERT(current_block()->HasPredecessor()); 8246 ASSERT(current_block()->HasPredecessor());
8204 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); 8247 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
8205 CHECK_ALIVE(VisitForValue(sub_expr)); 8248 CHECK_ALIVE(VisitForValue(sub_expr));
8206 HValue* value = Pop(); 8249 HValue* value = Pop();
8207 HIfContinuation continuation;
8208 if (expr->op() == Token::EQ_STRICT) { 8250 if (expr->op() == Token::EQ_STRICT) {
8209 IfBuilder if_nil(this); 8251 HConstant* nil_constant = nil == kNullValue
8210 if_nil.If<HCompareObjectEqAndBranch>( 8252 ? graph()->GetConstantNull()
8211 value, (nil == kNullValue) ? graph()->GetConstantNull() 8253 : graph()->GetConstantUndefined();
8212 : graph()->GetConstantUndefined()); 8254 HCompareObjectEqAndBranch* instr =
8213 if_nil.Then(); 8255 New<HCompareObjectEqAndBranch>(value, nil_constant);
8214 if_nil.Else(); 8256 instr->set_position(expr->position());
8215 if_nil.CaptureContinuation(&continuation); 8257 return ast_context()->ReturnControl(instr, expr->id());
8258 } else {
8259 ASSERT_EQ(Token::EQ, expr->op());
8260 Handle<Type> type = expr->combined_type()->Is(Type::None())
8261 ? handle(Type::Any(), isolate_)
8262 : expr->combined_type();
8263 HIfContinuation continuation;
8264 BuildCompareNil(value, type, expr->position(), &continuation);
8216 return ast_context()->ReturnContinuation(&continuation, expr->id()); 8265 return ast_context()->ReturnContinuation(&continuation, expr->id());
8217 } 8266 }
8218 Handle<Type> type = expr->combined_type()->Is(Type::None())
8219 ? handle(Type::Any(), isolate_) : expr->combined_type();
8220 BuildCompareNil(value, type, expr->position(), &continuation);
8221 return ast_context()->ReturnContinuation(&continuation, expr->id());
8222 } 8267 }
8223 8268
8224 8269
8225 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { 8270 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
8226 // If we share optimized code between different closures, the 8271 // If we share optimized code between different closures, the
8227 // this-function is not a constant, except inside an inlined body. 8272 // this-function is not a constant, except inside an inlined body.
8228 if (function_state()->outer() != NULL) { 8273 if (function_state()->outer() != NULL) {
8229 return New<HConstant>( 8274 return New<HConstant>(
8230 function_state()->compilation_info()->closure()); 8275 function_state()->compilation_info()->closure());
8231 } else { 8276 } else {
(...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after
9550 } else { 9595 } else {
9551 CodeStub::Major major_key = info->code_stub()->MajorKey(); 9596 CodeStub::Major major_key = info->code_stub()->MajorKey();
9552 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); 9597 PrintStringProperty("name", CodeStub::MajorName(major_key, false));
9553 PrintStringProperty("method", "stub"); 9598 PrintStringProperty("method", "stub");
9554 } 9599 }
9555 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 9600 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
9556 } 9601 }
9557 9602
9558 9603
9559 void HTracer::TraceLithium(const char* name, LChunk* chunk) { 9604 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
9560 ASSERT(!FLAG_parallel_recompilation); 9605 ASSERT(!FLAG_concurrent_recompilation);
9561 AllowHandleDereference allow_deref; 9606 AllowHandleDereference allow_deref;
9562 AllowDeferredHandleDereference allow_deferred_deref; 9607 AllowDeferredHandleDereference allow_deferred_deref;
9563 Trace(name, chunk->graph(), chunk); 9608 Trace(name, chunk->graph(), chunk);
9564 } 9609 }
9565 9610
9566 9611
9567 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { 9612 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
9568 ASSERT(!FLAG_parallel_recompilation); 9613 ASSERT(!FLAG_concurrent_recompilation);
9569 AllowHandleDereference allow_deref; 9614 AllowHandleDereference allow_deref;
9570 AllowDeferredHandleDereference allow_deferred_deref; 9615 AllowDeferredHandleDereference allow_deferred_deref;
9571 Trace(name, graph, NULL); 9616 Trace(name, graph, NULL);
9572 } 9617 }
9573 9618
9574 9619
9575 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { 9620 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
9576 Tag tag(this, "cfg"); 9621 Tag tag(this, "cfg");
9577 PrintStringProperty("name", name); 9622 PrintStringProperty("name", name);
9578 const ZoneList<HBasicBlock*>* blocks = graph->blocks(); 9623 const ZoneList<HBasicBlock*>* blocks = graph->blocks();
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
9845 if (ShouldProduceTraceOutput()) { 9890 if (ShouldProduceTraceOutput()) {
9846 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9891 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9847 } 9892 }
9848 9893
9849 #ifdef DEBUG 9894 #ifdef DEBUG
9850 graph_->Verify(false); // No full verify. 9895 graph_->Verify(false); // No full verify.
9851 #endif 9896 #endif
9852 } 9897 }
9853 9898
9854 } } // namespace v8::internal 9899 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-bch.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698