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

Side by Side Diff: src/hydrogen.cc

Issue 149413010: A64: Synchronize with r16024. (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-bce.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 26 matching lines...) Expand all
37 #include "hydrogen-bch.h" 37 #include "hydrogen-bch.h"
38 #include "hydrogen-canonicalize.h" 38 #include "hydrogen-canonicalize.h"
39 #include "hydrogen-dce.h" 39 #include "hydrogen-dce.h"
40 #include "hydrogen-dehoist.h" 40 #include "hydrogen-dehoist.h"
41 #include "hydrogen-deoptimizing-mark.h" 41 #include "hydrogen-deoptimizing-mark.h"
42 #include "hydrogen-environment-liveness.h" 42 #include "hydrogen-environment-liveness.h"
43 #include "hydrogen-escape-analysis.h" 43 #include "hydrogen-escape-analysis.h"
44 #include "hydrogen-infer-representation.h" 44 #include "hydrogen-infer-representation.h"
45 #include "hydrogen-infer-types.h" 45 #include "hydrogen-infer-types.h"
46 #include "hydrogen-gvn.h" 46 #include "hydrogen-gvn.h"
47 #include "hydrogen-mark-deoptimize.h"
47 #include "hydrogen-minus-zero.h" 48 #include "hydrogen-minus-zero.h"
48 #include "hydrogen-osr.h" 49 #include "hydrogen-osr.h"
49 #include "hydrogen-range-analysis.h" 50 #include "hydrogen-range-analysis.h"
50 #include "hydrogen-redundant-phi.h" 51 #include "hydrogen-redundant-phi.h"
51 #include "hydrogen-removable-simulates.h" 52 #include "hydrogen-removable-simulates.h"
52 #include "hydrogen-representation-changes.h" 53 #include "hydrogen-representation-changes.h"
53 #include "hydrogen-sce.h" 54 #include "hydrogen-sce.h"
54 #include "hydrogen-uint32-analysis.h" 55 #include "hydrogen-uint32-analysis.h"
55 #include "lithium-allocator.h" 56 #include "lithium-allocator.h"
56 #include "parser.h" 57 #include "parser.h"
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 } 604 }
604 } 605 }
605 } 606 }
606 607
607 #endif 608 #endif
608 609
609 610
610 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, 611 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
611 int32_t value) { 612 int32_t value) {
612 if (!pointer->is_set()) { 613 if (!pointer->is_set()) {
613 HConstant* constant = new(zone()) HConstant(value); 614 // Can't pass GetInvalidContext() to HConstant::New, because that will
615 // recursively call GetConstant
616 HConstant* constant = HConstant::New(zone(), NULL, value);
614 constant->InsertAfter(GetConstantUndefined()); 617 constant->InsertAfter(GetConstantUndefined());
615 pointer->set(constant); 618 pointer->set(constant);
616 } 619 }
617 return pointer->get(); 620 return pointer->get();
618 } 621 }
619 622
620 623
621 HConstant* HGraph::GetConstant0() { 624 HConstant* HGraph::GetConstant0() {
622 return GetConstant(&constant_0_, 0); 625 return GetConstant(&constant_0_, 0);
623 } 626 }
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 deopt_else_ = true; 832 deopt_else_ = true;
830 } else { 833 } else {
831 deopt_then_ = true; 834 deopt_then_ = true;
832 } 835 }
833 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); 836 builder_->Add<HDeoptimize>(Deoptimizer::EAGER);
834 } 837 }
835 838
836 839
837 void HGraphBuilder::IfBuilder::Return(HValue* value) { 840 void HGraphBuilder::IfBuilder::Return(HValue* value) {
838 HBasicBlock* block = builder_->current_block(); 841 HBasicBlock* block = builder_->current_block();
839 HValue* context = builder_->environment()->LookupContext();
840 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); 842 HValue* parameter_count = builder_->graph()->GetConstantMinus1();
841 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); 843 block->FinishExit(builder_->New<HReturn>(value, parameter_count));
842 builder_->set_current_block(NULL); 844 builder_->set_current_block(NULL);
843 if (did_else_) { 845 if (did_else_) {
844 first_false_block_ = NULL; 846 first_false_block_ = NULL;
845 } else { 847 } else {
846 first_true_block_ = NULL; 848 first_true_block_ = NULL;
847 } 849 }
848 } 850 }
849 851
850 852
851 void HGraphBuilder::IfBuilder::End() { 853 void HGraphBuilder::IfBuilder::End() {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 983 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
982 ASSERT(current_block() != NULL); 984 ASSERT(current_block() != NULL);
983 current_block()->AddInstruction(instr); 985 current_block()->AddInstruction(instr);
984 if (no_side_effects_scope_count_ > 0) { 986 if (no_side_effects_scope_count_ > 0) {
985 instr->SetFlag(HValue::kHasNoObservableSideEffects); 987 instr->SetFlag(HValue::kHasNoObservableSideEffects);
986 } 988 }
987 return instr; 989 return instr;
988 } 990 }
989 991
990 992
993 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter,
994 HValue* context) {
995 if (FLAG_native_code_counters && counter->Enabled()) {
996 HValue* reference = Add<HConstant>(ExternalReference(counter));
997 HValue* old_value = Add<HLoadNamedField>(reference,
998 HObjectAccess::ForCounter());
999 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1());
1000 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow
1001 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1002 new_value);
1003 }
1004 }
1005
1006
1007 void HGraphBuilder::AddSimulate(BailoutId id,
1008 RemovableSimulate removable) {
1009 ASSERT(current_block() != NULL);
1010 ASSERT(no_side_effects_scope_count_ == 0);
1011 current_block()->AddSimulate(id, removable);
1012 }
1013
1014
991 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 1015 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
992 HBasicBlock* b = graph()->CreateBasicBlock(); 1016 HBasicBlock* b = graph()->CreateBasicBlock();
993 b->SetInitialEnvironment(env); 1017 b->SetInitialEnvironment(env);
994 return b; 1018 return b;
995 } 1019 }
996 1020
997 1021
998 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 1022 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
999 HBasicBlock* header = graph()->CreateBasicBlock(); 1023 HBasicBlock* header = graph()->CreateBasicBlock();
1000 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 1024 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 from->last_environment()->Pop(); 1061 from->last_environment()->Pop();
1038 } 1062 }
1039 } 1063 }
1040 } else { 1064 } else {
1041 ASSERT(continuation->predecessors()->length() == 0); 1065 ASSERT(continuation->predecessors()->length() == 0);
1042 } 1066 }
1043 } 1067 }
1044 1068
1045 1069
1046 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { 1070 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) {
1047 HCheckMaps* check = HCheckMaps::New(obj, map, zone(), top_info()); 1071 return Add<HCheckMaps>(obj, map, top_info());
1048 AddInstruction(check);
1049 return check;
1050 } 1072 }
1051 1073
1052 1074
1053 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { 1075 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1054 if (object->type().IsJSObject()) return object; 1076 if (object->type().IsJSObject()) return object;
1055 return Add<HWrapReceiver>(object, function); 1077 return Add<HWrapReceiver>(object, function);
1056 } 1078 }
1057 1079
1058 1080
1059 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1081 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
(...skipping 11 matching lines...) Expand all
1071 length_checker.Then(); 1093 length_checker.Then();
1072 1094
1073 HValue* current_capacity = AddLoadFixedArrayLength(elements); 1095 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1074 1096
1075 IfBuilder capacity_checker(this); 1097 IfBuilder capacity_checker(this);
1076 1098
1077 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, 1099 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1078 Token::GTE); 1100 Token::GTE);
1079 capacity_checker.Then(); 1101 capacity_checker.Then();
1080 1102
1081 HValue* context = environment()->LookupContext(); 1103 HValue* context = environment()->context();
1082 1104
1083 HValue* new_capacity = BuildNewElementsCapacity(context, key); 1105 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1106 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap);
1107 IfBuilder key_checker(this);
1108 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
1109 key_checker.Then();
1110 key_checker.ElseDeopt();
1111 key_checker.End();
1084 1112
1113 HValue* new_capacity = BuildNewElementsCapacity(key);
1085 HValue* new_elements = BuildGrowElementsCapacity(object, elements, 1114 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1086 kind, kind, length, 1115 kind, kind, length,
1087 new_capacity); 1116 new_capacity);
1088 1117
1089 environment()->Push(new_elements); 1118 environment()->Push(new_elements);
1090 capacity_checker.Else(); 1119 capacity_checker.Else();
1091 1120
1092 environment()->Push(elements); 1121 environment()->Push(elements);
1093 capacity_checker.End(); 1122 capacity_checker.End();
1094 1123
1095 if (is_js_array) { 1124 if (is_js_array) {
1096 HValue* new_length = AddInstruction( 1125 HValue* new_length = AddInstruction(
1097 HAdd::New(zone, context, key, graph_->GetConstant1())); 1126 HAdd::New(zone, context, key, graph_->GetConstant1()));
1098 new_length->ClearFlag(HValue::kCanOverflow); 1127 new_length->ClearFlag(HValue::kCanOverflow);
1099 1128
1100 AddStore(object, HObjectAccess::ForArrayLength(kind), new_length); 1129 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1130 new_length);
1101 } 1131 }
1102 1132
1103 length_checker.Else(); 1133 length_checker.Else();
1104 Add<HBoundsCheck>(key, length); 1134 Add<HBoundsCheck>(key, length);
1105 1135
1106 environment()->Push(elements); 1136 environment()->Push(elements);
1107 length_checker.End(); 1137 length_checker.End();
1108 1138
1109 return environment()->Pop(); 1139 return environment()->Pop();
1110 } 1140 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 IsFastHoleyElementsKind(to_kind)); 1177 IsFastHoleyElementsKind(to_kind));
1148 1178
1149 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { 1179 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
1150 Add<HTrapAllocationMemento>(object); 1180 Add<HTrapAllocationMemento>(object);
1151 } 1181 }
1152 1182
1153 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { 1183 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
1154 HInstruction* elements = AddLoadElements(object); 1184 HInstruction* elements = AddLoadElements(object);
1155 1185
1156 HInstruction* empty_fixed_array = Add<HConstant>( 1186 HInstruction* empty_fixed_array = Add<HConstant>(
1157 isolate()->factory()->empty_fixed_array(), Representation::Tagged()); 1187 isolate()->factory()->empty_fixed_array());
1158 1188
1159 IfBuilder if_builder(this); 1189 IfBuilder if_builder(this);
1160 1190
1161 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); 1191 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1162 1192
1163 if_builder.Then(); 1193 if_builder.Then();
1164 1194
1165 HInstruction* elements_length = AddLoadFixedArrayLength(elements); 1195 HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1166 1196
1167 HInstruction* array_length = is_jsarray 1197 HInstruction* array_length = is_jsarray
1168 ? AddLoad(object, HObjectAccess::ForArrayLength(from_kind), NULL) 1198 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind))
1169 : elements_length; 1199 : elements_length;
1170 1200
1171 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, 1201 BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1172 array_length, elements_length); 1202 array_length, elements_length);
1173 1203
1174 if_builder.End(); 1204 if_builder.End();
1175 } 1205 }
1176 1206
1177 AddStore(object, HObjectAccess::ForMap(), map); 1207 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1178 } 1208 }
1179 1209
1180 1210
1181 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1211 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
1182 HValue* object, 1212 HValue* object,
1183 HValue* key, 1213 HValue* key,
1184 HValue* val, 1214 HValue* val,
1185 HCheckMaps* mapcheck, 1215 HCheckMaps* mapcheck,
1186 bool is_js_array, 1216 bool is_js_array,
1187 ElementsKind elements_kind, 1217 ElementsKind elements_kind,
1188 bool is_store, 1218 bool is_store,
1189 LoadKeyedHoleMode load_mode, 1219 LoadKeyedHoleMode load_mode,
1190 KeyedAccessStoreMode store_mode) { 1220 KeyedAccessStoreMode store_mode) {
1191 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); 1221 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
1192 Zone* zone = this->zone();
1193 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 1222 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
1194 // on a HElementsTransition instruction. The flag can also be removed if the 1223 // on a HElementsTransition instruction. The flag can also be removed if the
1195 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 1224 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
1196 // ElementsKind transitions. Finally, the dependency can be removed for stores 1225 // ElementsKind transitions. Finally, the dependency can be removed for stores
1197 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 1226 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
1198 // generated store code. 1227 // generated store code.
1199 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 1228 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
1200 (elements_kind == FAST_ELEMENTS && is_store)) { 1229 (elements_kind == FAST_ELEMENTS && is_store)) {
1201 if (mapcheck != NULL) { 1230 if (mapcheck != NULL) {
1202 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 1231 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
1203 } 1232 }
1204 } 1233 }
1205 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 1234 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
1206 bool fast_elements = IsFastObjectElementsKind(elements_kind); 1235 bool fast_elements = IsFastObjectElementsKind(elements_kind);
1207 HValue* elements = AddLoadElements(object, mapcheck); 1236 HValue* elements = AddLoadElements(object, mapcheck);
1208 if (is_store && (fast_elements || fast_smi_only_elements) && 1237 if (is_store && (fast_elements || fast_smi_only_elements) &&
1209 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 1238 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1210 HCheckMaps* check_cow_map = HCheckMaps::New( 1239 HCheckMaps* check_cow_map = Add<HCheckMaps>(
1211 elements, isolate()->factory()->fixed_array_map(), zone, top_info()); 1240 elements, isolate()->factory()->fixed_array_map(), top_info());
1212 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1241 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1213 AddInstruction(check_cow_map);
1214 } 1242 }
1215 HInstruction* length = NULL; 1243 HInstruction* length = NULL;
1216 if (is_js_array) { 1244 if (is_js_array) {
1217 length = AddLoad(object, HObjectAccess::ForArrayLength(elements_kind), 1245 length = Add<HLoadNamedField>(object,
1218 mapcheck); 1246 HObjectAccess::ForArrayLength(elements_kind), mapcheck);
1219 } else { 1247 } else {
1220 length = AddLoadFixedArrayLength(elements); 1248 length = AddLoadFixedArrayLength(elements);
1221 } 1249 }
1222 length->set_type(HType::Smi()); 1250 length->set_type(HType::Smi());
1223 HValue* checked_key = NULL; 1251 HValue* checked_key = NULL;
1224 if (IsExternalArrayElementsKind(elements_kind)) { 1252 if (IsExternalArrayElementsKind(elements_kind)) {
1225 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 1253 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
1226 NoObservableSideEffectsScope no_effects(this); 1254 NoObservableSideEffectsScope no_effects(this);
1227 HLoadExternalArrayPointer* external_elements = 1255 HLoadExternalArrayPointer* external_elements =
1228 Add<HLoadExternalArrayPointer>(elements); 1256 Add<HLoadExternalArrayPointer>(elements);
1229 IfBuilder length_checker(this); 1257 IfBuilder length_checker(this);
1230 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 1258 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
1231 length_checker.Then(); 1259 length_checker.Then();
1232 IfBuilder negative_checker(this); 1260 IfBuilder negative_checker(this);
1233 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 1261 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
1234 key, graph()->GetConstant0(), Token::GTE); 1262 key, graph()->GetConstant0(), Token::GTE);
1235 negative_checker.Then(); 1263 negative_checker.Then();
1236 HInstruction* result = AddExternalArrayElementAccess( 1264 HInstruction* result = AddExternalArrayElementAccess(
1237 external_elements, key, val, bounds_check, elements_kind, is_store); 1265 external_elements, key, val, bounds_check, elements_kind, is_store);
1238 negative_checker.ElseDeopt(); 1266 negative_checker.ElseDeopt();
(...skipping 29 matching lines...) Expand all
1268 } else { 1296 } else {
1269 checked_key = Add<HBoundsCheck>(key, length); 1297 checked_key = Add<HBoundsCheck>(key, length);
1270 1298
1271 if (is_store && (fast_elements || fast_smi_only_elements)) { 1299 if (is_store && (fast_elements || fast_smi_only_elements)) {
1272 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 1300 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1273 NoObservableSideEffectsScope no_effects(this); 1301 NoObservableSideEffectsScope no_effects(this);
1274 1302
1275 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, 1303 elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
1276 length); 1304 length);
1277 } else { 1305 } else {
1278 HCheckMaps* check_cow_map = HCheckMaps::New( 1306 HCheckMaps* check_cow_map = Add<HCheckMaps>(
1279 elements, isolate()->factory()->fixed_array_map(), 1307 elements, isolate()->factory()->fixed_array_map(),
1280 zone, top_info()); 1308 top_info());
1281 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1309 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1282 AddInstruction(check_cow_map);
1283 } 1310 }
1284 } 1311 }
1285 } 1312 }
1286 return AddFastElementAccess(elements, checked_key, val, mapcheck, 1313 return AddFastElementAccess(elements, checked_key, val, mapcheck,
1287 elements_kind, is_store, load_mode, store_mode); 1314 elements_kind, is_store, load_mode, store_mode);
1288 } 1315 }
1289 1316
1290 1317
1291 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, 1318 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
1292 ElementsKind kind,
1293 HValue* capacity) { 1319 HValue* capacity) {
1294 Zone* zone = this->zone(); 1320 int elements_size;
1321 InstanceType instance_type;
1295 1322
1296 int elements_size = IsFastDoubleElementsKind(kind) 1323 if (IsFastDoubleElementsKind(kind)) {
1297 ? kDoubleSize : kPointerSize; 1324 elements_size = kDoubleSize;
1325 instance_type = FIXED_DOUBLE_ARRAY_TYPE;
1326 } else {
1327 elements_size = kPointerSize;
1328 instance_type = FIXED_ARRAY_TYPE;
1329 }
1330
1298 HConstant* elements_size_value = Add<HConstant>(elements_size); 1331 HConstant* elements_size_value = Add<HConstant>(elements_size);
1299 HValue* mul = AddInstruction( 1332 HValue* mul = Add<HMul>(capacity, elements_size_value);
1300 HMul::New(zone, context, capacity, elements_size_value));
1301 mul->ClearFlag(HValue::kCanOverflow); 1333 mul->ClearFlag(HValue::kCanOverflow);
1302 1334
1303 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); 1335 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
1304 HValue* total_size = AddInstruction( 1336 HValue* total_size = Add<HAdd>(mul, header_size);
1305 HAdd::New(zone, context, mul, header_size));
1306 total_size->ClearFlag(HValue::kCanOverflow); 1337 total_size->ClearFlag(HValue::kCanOverflow);
1307 1338
1308 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); 1339 return Add<HAllocate>(total_size, HType::JSArray(),
1309 if (isolate()->heap()->ShouldGloballyPretenure()) { 1340 isolate()->heap()->GetPretenureMode(), instance_type);
1310 // TODO(hpayer): When pretenuring can be internalized, flags can become
1311 // private to HAllocate.
1312 if (IsFastDoubleElementsKind(kind)) {
1313 flags = static_cast<HAllocate::Flags>(
1314 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE);
1315 } else {
1316 flags = static_cast<HAllocate::Flags>(
1317 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
1318 }
1319 }
1320
1321 return Add<HAllocate>(context, total_size, HType::JSArray(), flags);
1322 } 1341 }
1323 1342
1324 1343
1325 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, 1344 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
1326 ElementsKind kind, 1345 ElementsKind kind,
1327 HValue* capacity) { 1346 HValue* capacity) {
1328 Factory* factory = isolate()->factory(); 1347 Factory* factory = isolate()->factory();
1329 Handle<Map> map = IsFastDoubleElementsKind(kind) 1348 Handle<Map> map = IsFastDoubleElementsKind(kind)
1330 ? factory->fixed_double_array_map() 1349 ? factory->fixed_double_array_map()
1331 : factory->fixed_array_map(); 1350 : factory->fixed_array_map();
1332 1351
1333 AddStoreMapConstant(elements, map); 1352 AddStoreMapConstant(elements, map);
1334 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity); 1353 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
1354 capacity);
1335 } 1355 }
1336 1356
1337 1357
1338 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( 1358 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
1339 HValue* context,
1340 ElementsKind kind, 1359 ElementsKind kind,
1341 HValue* capacity) { 1360 HValue* capacity) {
1342 HValue* new_elements = BuildAllocateElements(context, kind, capacity); 1361 // The HForceRepresentation is to prevent possible deopt on int-smi
1362 // conversion after allocation but before the new object fields are set.
1363 capacity = Add<HForceRepresentation>(capacity, Representation::Smi());
1364 HValue* new_elements = BuildAllocateElements(kind, capacity);
1343 BuildInitializeElementsHeader(new_elements, kind, capacity); 1365 BuildInitializeElementsHeader(new_elements, kind, capacity);
1344 return new_elements; 1366 return new_elements;
1345 } 1367 }
1346 1368
1347 1369
1348 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, 1370 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
1349 HValue* array_map, 1371 HValue* array_map,
1350 AllocationSiteMode mode, 1372 AllocationSiteMode mode,
1351 ElementsKind elements_kind, 1373 ElementsKind elements_kind,
1352 HValue* allocation_site_payload, 1374 HValue* allocation_site_payload,
1353 HValue* length_field) { 1375 HValue* length_field) {
1354 1376
1355 AddStore(array, HObjectAccess::ForMap(), array_map); 1377 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
1356 1378
1357 HConstant* empty_fixed_array = 1379 HConstant* empty_fixed_array =
1358 Add<HConstant>(isolate()->factory()->empty_fixed_array()); 1380 Add<HConstant>(isolate()->factory()->empty_fixed_array());
1359 1381
1360 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); 1382 HObjectAccess access = HObjectAccess::ForPropertiesPointer();
1361 AddStore(array, access, empty_fixed_array); 1383 Add<HStoreNamedField>(array, access, empty_fixed_array);
1362 AddStore(array, HObjectAccess::ForArrayLength(elements_kind), length_field); 1384 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind),
1385 length_field);
1363 1386
1364 if (mode == TRACK_ALLOCATION_SITE) { 1387 if (mode == TRACK_ALLOCATION_SITE) {
1365 BuildCreateAllocationMemento(array, 1388 BuildCreateAllocationMemento(array,
1366 JSArray::kSize, 1389 JSArray::kSize,
1367 allocation_site_payload); 1390 allocation_site_payload);
1368 } 1391 }
1369 1392
1370 int elements_location = JSArray::kSize; 1393 int elements_location = JSArray::kSize;
1371 if (mode == TRACK_ALLOCATION_SITE) { 1394 if (mode == TRACK_ALLOCATION_SITE) {
1372 elements_location += AllocationMemento::kSize; 1395 elements_location += AllocationMemento::kSize;
1373 } 1396 }
1374 1397
1375 HInnerAllocatedObject* elements = 1398 HValue* elements = Add<HInnerAllocatedObject>(array, elements_location);
1376 Add<HInnerAllocatedObject>(array, elements_location); 1399 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements);
1377 AddStore(array, HObjectAccess::ForElementsPointer(), elements); 1400 return static_cast<HInnerAllocatedObject*>(elements);
1378 return elements;
1379 } 1401 }
1380 1402
1381 1403
1382 HInstruction* HGraphBuilder::AddExternalArrayElementAccess( 1404 HInstruction* HGraphBuilder::AddExternalArrayElementAccess(
1383 HValue* external_elements, 1405 HValue* external_elements,
1384 HValue* checked_key, 1406 HValue* checked_key,
1385 HValue* val, 1407 HValue* val,
1386 HValue* dependency, 1408 HValue* dependency,
1387 ElementsKind elements_kind, 1409 ElementsKind elements_kind,
1388 bool is_store) { 1410 bool is_store) {
(...skipping 22 matching lines...) Expand all
1411 case FAST_HOLEY_ELEMENTS: 1433 case FAST_HOLEY_ELEMENTS:
1412 case FAST_HOLEY_DOUBLE_ELEMENTS: 1434 case FAST_HOLEY_DOUBLE_ELEMENTS:
1413 case DICTIONARY_ELEMENTS: 1435 case DICTIONARY_ELEMENTS:
1414 case NON_STRICT_ARGUMENTS_ELEMENTS: 1436 case NON_STRICT_ARGUMENTS_ELEMENTS:
1415 UNREACHABLE(); 1437 UNREACHABLE();
1416 break; 1438 break;
1417 } 1439 }
1418 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); 1440 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind);
1419 } else { 1441 } else {
1420 ASSERT(val == NULL); 1442 ASSERT(val == NULL);
1421 HLoadKeyed* load = Add<HLoadKeyed>(external_elements, checked_key, 1443 HLoadKeyed* load = Add<HLoadKeyed>(external_elements,
1422 dependency, elements_kind); 1444 checked_key,
1445 dependency,
1446 elements_kind);
1423 if (FLAG_opt_safe_uint32_operations && 1447 if (FLAG_opt_safe_uint32_operations &&
1424 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 1448 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
1425 graph()->RecordUint32Instruction(load); 1449 graph()->RecordUint32Instruction(load);
1426 } 1450 }
1427 return load; 1451 return load;
1428 } 1452 }
1429 } 1453 }
1430 1454
1431 1455
1432 HInstruction* HGraphBuilder::AddFastElementAccess( 1456 HInstruction* HGraphBuilder::AddFastElementAccess(
(...skipping 21 matching lines...) Expand all
1454 } 1478 }
1455 } 1479 }
1456 // It's an element load (!is_store). 1480 // It's an element load (!is_store).
1457 return Add<HLoadKeyed>( 1481 return Add<HLoadKeyed>(
1458 elements, checked_key, load_dependency, elements_kind, load_mode); 1482 elements, checked_key, load_dependency, elements_kind, load_mode);
1459 } 1483 }
1460 1484
1461 1485
1462 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, 1486 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
1463 HValue* typecheck) { 1487 HValue* typecheck) {
1464 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); 1488 return Add<HLoadNamedField>(object,
1489 HObjectAccess::ForElementsPointer(),
1490 typecheck);
1465 } 1491 }
1466 1492
1467 1493
1468 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { 1494 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) {
1469 return AddLoad(object, HObjectAccess::ForFixedArrayLength()); 1495 return Add<HLoadNamedField>(object,
1496 HObjectAccess::ForFixedArrayLength());
1470 } 1497 }
1471 1498
1472 1499
1473 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, 1500 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
1474 HValue* old_capacity) { 1501 HValue* half_old_capacity = Add<HShr>(old_capacity, graph_->GetConstant1());
1475 Zone* zone = this->zone();
1476 HValue* half_old_capacity =
1477 AddInstruction(HShr::New(zone, context, old_capacity,
1478 graph_->GetConstant1()));
1479 half_old_capacity->ClearFlag(HValue::kCanOverflow);
1480 1502
1481 HValue* new_capacity = AddInstruction( 1503 HValue* new_capacity = Add<HAdd>(half_old_capacity, old_capacity);
1482 HAdd::New(zone, context, half_old_capacity, old_capacity));
1483 new_capacity->ClearFlag(HValue::kCanOverflow); 1504 new_capacity->ClearFlag(HValue::kCanOverflow);
1484 1505
1485 HValue* min_growth = Add<HConstant>(16); 1506 HValue* min_growth = Add<HConstant>(16);
1486 1507
1487 new_capacity = AddInstruction( 1508 new_capacity = Add<HAdd>(new_capacity, min_growth);
1488 HAdd::New(zone, context, new_capacity, min_growth));
1489 new_capacity->ClearFlag(HValue::kCanOverflow); 1509 new_capacity->ClearFlag(HValue::kCanOverflow);
1490 1510
1491 return new_capacity; 1511 return new_capacity;
1492 } 1512 }
1493 1513
1494 1514
1495 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { 1515 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
1496 Heap* heap = isolate()->heap(); 1516 Heap* heap = isolate()->heap();
1497 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize 1517 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize
1498 : kPointerSize; 1518 : kPointerSize;
1499 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; 1519 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size;
1500 max_size -= JSArray::kSize / element_size; 1520 max_size -= JSArray::kSize / element_size;
1501 HConstant* max_size_constant = Add<HConstant>(max_size); 1521 HConstant* max_size_constant = Add<HConstant>(max_size);
1502 // Since we're forcing Integer32 representation for this HBoundsCheck,
1503 // there's no need to Smi-check the index.
1504 Add<HBoundsCheck>(length, max_size_constant); 1522 Add<HBoundsCheck>(length, max_size_constant);
1505 } 1523 }
1506 1524
1507 1525
1508 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, 1526 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
1509 HValue* elements, 1527 HValue* elements,
1510 ElementsKind kind, 1528 ElementsKind kind,
1511 ElementsKind new_kind, 1529 ElementsKind new_kind,
1512 HValue* length, 1530 HValue* length,
1513 HValue* new_capacity) { 1531 HValue* new_capacity) {
1514 HValue* context = environment()->LookupContext();
1515
1516 BuildNewSpaceArrayCheck(new_capacity, new_kind); 1532 BuildNewSpaceArrayCheck(new_capacity, new_kind);
1517 1533
1518 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( 1534 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
1519 context, new_kind, new_capacity); 1535 new_kind, new_capacity);
1520 1536
1521 BuildCopyElements(context, elements, kind, 1537 BuildCopyElements(elements, kind,
1522 new_elements, new_kind, 1538 new_elements, new_kind,
1523 length, new_capacity); 1539 length, new_capacity);
1524 1540
1525 AddStore(object, HObjectAccess::ForElementsPointer(), new_elements); 1541 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
1542 new_elements);
1526 1543
1527 return new_elements; 1544 return new_elements;
1528 } 1545 }
1529 1546
1530 1547
1531 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, 1548 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
1532 HValue* elements,
1533 ElementsKind elements_kind, 1549 ElementsKind elements_kind,
1534 HValue* from, 1550 HValue* from,
1535 HValue* to) { 1551 HValue* to) {
1536 // Fast elements kinds need to be initialized in case statements below cause 1552 // Fast elements kinds need to be initialized in case statements below cause
1537 // a garbage collection. 1553 // a garbage collection.
1538 Factory* factory = isolate()->factory(); 1554 Factory* factory = isolate()->factory();
1539 1555
1540 double nan_double = FixedDoubleArray::hole_nan_as_double(); 1556 double nan_double = FixedDoubleArray::hole_nan_as_double();
1541 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) 1557 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
1542 ? Add<HConstant>(factory->the_hole_value()) 1558 ? Add<HConstant>(factory->the_hole_value())
(...skipping 21 matching lines...) Expand all
1564 if (IsFastSmiOrObjectElementsKind(elements_kind)) { 1580 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
1565 elements_kind = FAST_HOLEY_ELEMENTS; 1581 elements_kind = FAST_HOLEY_ELEMENTS;
1566 } 1582 }
1567 1583
1568 if (unfold_loop) { 1584 if (unfold_loop) {
1569 for (int i = 0; i < initial_capacity; i++) { 1585 for (int i = 0; i < initial_capacity; i++) {
1570 HInstruction* key = Add<HConstant>(i); 1586 HInstruction* key = Add<HConstant>(i);
1571 Add<HStoreKeyed>(elements, key, hole, elements_kind); 1587 Add<HStoreKeyed>(elements, key, hole, elements_kind);
1572 } 1588 }
1573 } else { 1589 } else {
1574 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); 1590 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
1575 1591
1576 HValue* key = builder.BeginBody(from, to, Token::LT); 1592 HValue* key = builder.BeginBody(from, to, Token::LT);
1577 1593
1578 Add<HStoreKeyed>(elements, key, hole, elements_kind); 1594 Add<HStoreKeyed>(elements, key, hole, elements_kind);
1579 1595
1580 builder.EndBody(); 1596 builder.EndBody();
1581 } 1597 }
1582 } 1598 }
1583 1599
1584 1600
1585 void HGraphBuilder::BuildCopyElements(HValue* context, 1601 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
1586 HValue* from_elements,
1587 ElementsKind from_elements_kind, 1602 ElementsKind from_elements_kind,
1588 HValue* to_elements, 1603 HValue* to_elements,
1589 ElementsKind to_elements_kind, 1604 ElementsKind to_elements_kind,
1590 HValue* length, 1605 HValue* length,
1591 HValue* capacity) { 1606 HValue* capacity) {
1592 bool pre_fill_with_holes = 1607 bool pre_fill_with_holes =
1593 IsFastDoubleElementsKind(from_elements_kind) && 1608 IsFastDoubleElementsKind(from_elements_kind) &&
1594 IsFastObjectElementsKind(to_elements_kind); 1609 IsFastObjectElementsKind(to_elements_kind);
1595 1610
1596 if (pre_fill_with_holes) { 1611 if (pre_fill_with_holes) {
1597 // If the copy might trigger a GC, make sure that the FixedArray is 1612 // If the copy might trigger a GC, make sure that the FixedArray is
1598 // pre-initialized with holes to make sure that it's always in a consistent 1613 // pre-initialized with holes to make sure that it's always in a consistent
1599 // state. 1614 // state.
1600 BuildFillElementsWithHole(context, to_elements, to_elements_kind, 1615 BuildFillElementsWithHole(to_elements, to_elements_kind,
1601 graph()->GetConstant0(), capacity); 1616 graph()->GetConstant0(), capacity);
1602 } 1617 }
1603 1618
1604 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); 1619 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
1605 1620
1606 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); 1621 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
1607 1622
1608 HValue* element = Add<HLoadKeyed>(from_elements, key, 1623 HValue* element = Add<HLoadKeyed>(from_elements, key,
1609 static_cast<HValue*>(NULL), 1624 static_cast<HValue*>(NULL),
1610 from_elements_kind, 1625 from_elements_kind,
1611 ALLOW_RETURN_HOLE); 1626 ALLOW_RETURN_HOLE);
1612 1627
1613 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) 1628 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind)
1614 ? FAST_HOLEY_ELEMENTS : to_elements_kind; 1629 ? FAST_HOLEY_ELEMENTS : to_elements_kind;
1615 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key, 1630 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key,
1616 element, holey_kind); 1631 element, holey_kind);
1617 // Allow NaN hole values to converted to their tagged counterparts. 1632 // Allow NaN hole values to converted to their tagged counterparts.
1618 if (IsFastHoleyElementsKind(to_elements_kind)) { 1633 if (IsFastHoleyElementsKind(to_elements_kind)) {
1619 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); 1634 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN);
1620 } 1635 }
1621 1636
1622 builder.EndBody(); 1637 builder.EndBody();
1623 1638
1624 if (!pre_fill_with_holes && length != capacity) { 1639 if (!pre_fill_with_holes && length != capacity) {
1625 // Fill unused capacity with the hole. 1640 // Fill unused capacity with the hole.
1626 BuildFillElementsWithHole(context, to_elements, to_elements_kind, 1641 BuildFillElementsWithHole(to_elements, to_elements_kind,
1627 key, capacity); 1642 key, capacity);
1628 } 1643 }
1629 } 1644 }
1630 1645
1631 1646
1632 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, 1647 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate,
1633 HValue* boilerplate,
1634 HValue* allocation_site, 1648 HValue* allocation_site,
1635 AllocationSiteMode mode, 1649 AllocationSiteMode mode,
1636 ElementsKind kind, 1650 ElementsKind kind,
1637 int length) { 1651 int length) {
1638 NoObservableSideEffectsScope no_effects(this); 1652 NoObservableSideEffectsScope no_effects(this);
1639 1653
1640 // All sizes here are multiples of kPointerSize. 1654 // All sizes here are multiples of kPointerSize.
1641 int size = JSArray::kSize; 1655 int size = JSArray::kSize;
1642 if (mode == TRACK_ALLOCATION_SITE) { 1656 if (mode == TRACK_ALLOCATION_SITE) {
1643 size += AllocationMemento::kSize; 1657 size += AllocationMemento::kSize;
1644 } 1658 }
1645 int elems_offset = size; 1659 int elems_offset = size;
1660 InstanceType instance_type = IsFastDoubleElementsKind(kind) ?
1661 FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
1646 if (length > 0) { 1662 if (length > 0) {
1647 size += IsFastDoubleElementsKind(kind) 1663 size += IsFastDoubleElementsKind(kind)
1648 ? FixedDoubleArray::SizeFor(length) 1664 ? FixedDoubleArray::SizeFor(length)
1649 : FixedArray::SizeFor(length); 1665 : FixedArray::SizeFor(length);
1650 } 1666 }
1651 1667
1652 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind);
1653 // Allocate both the JS array and the elements array in one big 1668 // Allocate both the JS array and the elements array in one big
1654 // allocation. This avoids multiple limit checks. 1669 // allocation. This avoids multiple limit checks.
1655 HValue* size_in_bytes = Add<HConstant>(size); 1670 HValue* size_in_bytes = Add<HConstant>(size);
1656 HInstruction* object = Add<HAllocate>(context, 1671 HInstruction* object = Add<HAllocate>(size_in_bytes,
1657 size_in_bytes,
1658 HType::JSObject(), 1672 HType::JSObject(),
1659 allocate_flags); 1673 NOT_TENURED,
1674 instance_type);
1660 1675
1661 // Copy the JS array part. 1676 // Copy the JS array part.
1662 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 1677 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
1663 if ((i != JSArray::kElementsOffset) || (length == 0)) { 1678 if ((i != JSArray::kElementsOffset) || (length == 0)) {
1664 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); 1679 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i);
1665 AddStore(object, access, AddLoad(boilerplate, access)); 1680 Add<HStoreNamedField>(object, access,
1681 Add<HLoadNamedField>(boilerplate, access));
1666 } 1682 }
1667 } 1683 }
1668 1684
1669 // Create an allocation site info if requested. 1685 // Create an allocation site info if requested.
1670 if (mode == TRACK_ALLOCATION_SITE) { 1686 if (mode == TRACK_ALLOCATION_SITE) {
1671 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); 1687 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site);
1672 } 1688 }
1673 1689
1674 if (length > 0) { 1690 if (length > 0) {
1675 // Get hold of the elements array of the boilerplate and setup the 1691 // Get hold of the elements array of the boilerplate and setup the
1676 // elements pointer in the resulting object. 1692 // elements pointer in the resulting object.
1677 HValue* boilerplate_elements = AddLoadElements(boilerplate); 1693 HValue* boilerplate_elements = AddLoadElements(boilerplate);
1678 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); 1694 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset);
1679 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); 1695 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
1696 object_elements);
1680 1697
1681 // Copy the elements array header. 1698 // Copy the elements array header.
1682 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { 1699 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
1683 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); 1700 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
1684 AddStore(object_elements, access, AddLoad(boilerplate_elements, access)); 1701 Add<HStoreNamedField>(object_elements, access,
1702 Add<HLoadNamedField>(boilerplate_elements, access));
1685 } 1703 }
1686 1704
1687 // Copy the elements array contents. 1705 // Copy the elements array contents.
1688 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold 1706 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold
1689 // copying loops with constant length up to a given boundary and use this 1707 // copying loops with constant length up to a given boundary and use this
1690 // helper here instead. 1708 // helper here instead.
1691 for (int i = 0; i < length; i++) { 1709 for (int i = 0; i < length; i++) {
1692 HValue* key_constant = Add<HConstant>(i); 1710 HValue* key_constant = Add<HConstant>(i);
1693 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, 1711 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant,
1694 static_cast<HValue*>(NULL), kind); 1712 static_cast<HValue*>(NULL), kind);
1695 Add<HStoreKeyed>(object_elements, key_constant, value, kind); 1713 Add<HStoreKeyed>(object_elements, key_constant, value, kind);
1696 } 1714 }
1697 } 1715 }
1698 1716
1699 return object; 1717 return object;
1700 } 1718 }
1701 1719
1702 1720
1703 HInstruction* HGraphBuilder::BuildUnaryMathOp( 1721 HInstruction* HGraphBuilder::BuildUnaryMathOp(
1704 HValue* input, Handle<Type> type, Token::Value operation) { 1722 HValue* input, Handle<Type> type, Token::Value operation) {
1705 // We only handle the numeric cases here 1723 // We only handle the numeric cases here
1706 type = handle( 1724 type = handle(
1707 Type::Intersect(type, handle(Type::Number(), isolate())), isolate()); 1725 Type::Intersect(type, handle(Type::Number(), isolate())), isolate());
1708 1726
1709 switch (operation) { 1727 switch (operation) {
1710 default: 1728 default:
1711 UNREACHABLE(); 1729 UNREACHABLE();
1712 case Token::SUB: { 1730 case Token::SUB: {
1713 HInstruction* instr = 1731 HInstruction* instr =
1714 HMul::New(zone(), environment()->LookupContext(), 1732 NewUncasted<HMul>(input, graph()->GetConstantMinus1());
1715 input, graph()->GetConstantMinus1());
1716 Representation rep = Representation::FromType(type); 1733 Representation rep = Representation::FromType(type);
1717 if (type->Is(Type::None())) { 1734 if (type->Is(Type::None())) {
1718 Add<HDeoptimize>(Deoptimizer::SOFT); 1735 Add<HDeoptimize>(Deoptimizer::SOFT);
1719 } 1736 }
1720 if (instr->IsBinaryOperation()) { 1737 if (instr->IsBinaryOperation()) {
1721 HBinaryOperation* binop = HBinaryOperation::cast(instr); 1738 HBinaryOperation* binop = HBinaryOperation::cast(instr);
1722 binop->set_observed_input_representation(1, rep); 1739 binop->set_observed_input_representation(1, rep);
1723 binop->set_observed_input_representation(2, rep); 1740 binop->set_observed_input_representation(2, rep);
1724 } 1741 }
1725 return instr; 1742 return instr;
1726 } 1743 }
1727 case Token::BIT_NOT: 1744 case Token::BIT_NOT:
1728 if (type->Is(Type::None())) { 1745 if (type->Is(Type::None())) {
1729 Add<HDeoptimize>(Deoptimizer::SOFT); 1746 Add<HDeoptimize>(Deoptimizer::SOFT);
1730 } 1747 }
1731 return new(zone()) HBitNot(input); 1748 return New<HBitNot>(input);
1732 } 1749 }
1733 } 1750 }
1734 1751
1735 1752
1736 void HGraphBuilder::BuildCompareNil( 1753 void HGraphBuilder::BuildCompareNil(
1737 HValue* value, 1754 HValue* value,
1738 Handle<Type> type, 1755 Handle<Type> type,
1739 int position, 1756 int position,
1740 HIfContinuation* continuation) { 1757 HIfContinuation* continuation) {
1741 IfBuilder if_nil(this, position); 1758 IfBuilder if_nil(this, position);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, 1793 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object,
1777 int previous_object_size, 1794 int previous_object_size,
1778 HValue* alloc_site) { 1795 HValue* alloc_site) {
1779 ASSERT(alloc_site != NULL); 1796 ASSERT(alloc_site != NULL);
1780 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( 1797 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>(
1781 previous_object, previous_object_size); 1798 previous_object, previous_object_size);
1782 Handle<Map> alloc_memento_map( 1799 Handle<Map> alloc_memento_map(
1783 isolate()->heap()->allocation_memento_map()); 1800 isolate()->heap()->allocation_memento_map());
1784 AddStoreMapConstant(alloc_memento, alloc_memento_map); 1801 AddStoreMapConstant(alloc_memento, alloc_memento_map);
1785 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); 1802 HObjectAccess access = HObjectAccess::ForAllocationMementoSite();
1786 AddStore(alloc_memento, access, alloc_site); 1803 Add<HStoreNamedField>(alloc_memento, access, alloc_site);
1787 return alloc_memento; 1804 return alloc_memento;
1788 } 1805 }
1789 1806
1790 1807
1791 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { 1808 HInstruction* HGraphBuilder::BuildGetNativeContext() {
1792 // Get the global context, then the native context 1809 // Get the global context, then the native context
1793 HInstruction* global_object = Add<HGlobalObject>(context); 1810 HInstruction* global_object = Add<HGlobalObject>();
1794 HObjectAccess access = HObjectAccess::ForJSObjectOffset( 1811 HObjectAccess access = HObjectAccess::ForJSObjectOffset(
1795 GlobalObject::kNativeContextOffset); 1812 GlobalObject::kNativeContextOffset);
1796 return AddLoad(global_object, access); 1813 return Add<HLoadNamedField>(global_object, access);
1797 } 1814 }
1798 1815
1799 1816
1800 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { 1817 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
1801 HInstruction* native_context = BuildGetNativeContext(context); 1818 HInstruction* native_context = BuildGetNativeContext();
1802 HInstruction* index = 1819 HInstruction* index =
1803 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); 1820 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
1804 return Add<HLoadKeyed>( 1821 return Add<HLoadKeyed>(
1805 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 1822 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1806 } 1823 }
1807 1824
1808 1825
1809 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, 1826 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
1810 ElementsKind kind, 1827 ElementsKind kind,
1811 HValue* allocation_site_payload, 1828 HValue* allocation_site_payload,
(...skipping 13 matching lines...) Expand all
1825 ElementsKind kind, 1842 ElementsKind kind,
1826 HValue* constructor_function) : 1843 HValue* constructor_function) :
1827 builder_(builder), 1844 builder_(builder),
1828 kind_(kind), 1845 kind_(kind),
1829 mode_(DONT_TRACK_ALLOCATION_SITE), 1846 mode_(DONT_TRACK_ALLOCATION_SITE),
1830 allocation_site_payload_(NULL), 1847 allocation_site_payload_(NULL),
1831 constructor_function_(constructor_function) { 1848 constructor_function_(constructor_function) {
1832 } 1849 }
1833 1850
1834 1851
1835 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { 1852 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
1836 if (kind_ == GetInitialFastElementsKind()) { 1853 if (kind_ == GetInitialFastElementsKind()) {
1837 // No need for a context lookup if the kind_ matches the initial 1854 // No need for a context lookup if the kind_ matches the initial
1838 // map, because we can just load the map in that case. 1855 // map, because we can just load the map in that case.
1839 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 1856 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1840 return builder()->AddInstruction( 1857 return builder()->AddInstruction(
1841 builder()->BuildLoadNamedField(constructor_function_, access)); 1858 builder()->BuildLoadNamedField(constructor_function_, access));
1842 } 1859 }
1843 1860
1844 HInstruction* native_context = builder()->BuildGetNativeContext(context); 1861 HInstruction* native_context = builder()->BuildGetNativeContext();
1845 HInstruction* index = builder()->Add<HConstant>( 1862 HInstruction* index = builder()->Add<HConstant>(
1846 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 1863 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
1847 1864
1848 HInstruction* map_array = builder()->Add<HLoadKeyed>( 1865 HInstruction* map_array = builder()->Add<HLoadKeyed>(
1849 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 1866 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1850 1867
1851 HInstruction* kind_index = builder()->Add<HConstant>(kind_); 1868 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
1852 1869
1853 return builder()->Add<HLoadKeyed>( 1870 return builder()->Add<HLoadKeyed>(
1854 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 1871 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1855 } 1872 }
1856 1873
1857 1874
1858 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { 1875 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
1859 // Find the map near the constructor function 1876 // Find the map near the constructor function
1860 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 1877 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1861 return builder()->AddInstruction( 1878 return builder()->AddInstruction(
1862 builder()->BuildLoadNamedField(constructor_function_, access)); 1879 builder()->BuildLoadNamedField(constructor_function_, access));
1863 } 1880 }
1864 1881
1865 1882
1866 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( 1883 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
1867 HValue* length_node) { 1884 HValue* length_node) {
1868 HValue* context = builder()->environment()->LookupContext();
1869 ASSERT(length_node != NULL); 1885 ASSERT(length_node != NULL);
1870 1886
1871 int base_size = JSArray::kSize; 1887 int base_size = JSArray::kSize;
1872 if (mode_ == TRACK_ALLOCATION_SITE) { 1888 if (mode_ == TRACK_ALLOCATION_SITE) {
1873 base_size += AllocationMemento::kSize; 1889 base_size += AllocationMemento::kSize;
1874 } 1890 }
1875 1891
1876 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); 1892 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
1877 base_size += FixedArray::kHeaderSize; 1893 base_size += FixedArray::kHeaderSize;
1878 1894
1879 HInstruction* elements_size_value = 1895 HInstruction* elements_size_value =
1880 builder()->Add<HConstant>(elements_size()); 1896 builder()->Add<HConstant>(elements_size());
1881 HInstruction* mul = HMul::New(zone(), context, length_node, 1897 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value);
1882 elements_size_value);
1883 mul->ClearFlag(HValue::kCanOverflow); 1898 mul->ClearFlag(HValue::kCanOverflow);
1884 builder()->AddInstruction(mul);
1885 1899
1886 HInstruction* base = builder()->Add<HConstant>(base_size); 1900 HInstruction* base = builder()->Add<HConstant>(base_size);
1887 HInstruction* total_size = HAdd::New(zone(), context, base, mul); 1901 HInstruction* total_size = builder()->Add<HAdd>(base, mul);
1888 total_size->ClearFlag(HValue::kCanOverflow); 1902 total_size->ClearFlag(HValue::kCanOverflow);
1889 builder()->AddInstruction(total_size);
1890 return total_size; 1903 return total_size;
1891 } 1904 }
1892 1905
1893 1906
1894 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { 1907 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() {
1895 int base_size = JSArray::kSize; 1908 int base_size = JSArray::kSize;
1896 if (mode_ == TRACK_ALLOCATION_SITE) { 1909 if (mode_ == TRACK_ALLOCATION_SITE) {
1897 base_size += AllocationMemento::kSize; 1910 base_size += AllocationMemento::kSize;
1898 } 1911 }
1899 1912
(...skipping 20 matching lines...) Expand all
1920 bool fill_with_hole) { 1933 bool fill_with_hole) {
1921 HValue* size_in_bytes = EstablishAllocationSize(capacity); 1934 HValue* size_in_bytes = EstablishAllocationSize(capacity);
1922 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); 1935 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole);
1923 } 1936 }
1924 1937
1925 1938
1926 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, 1939 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
1927 HValue* capacity, 1940 HValue* capacity,
1928 HValue* length_field, 1941 HValue* length_field,
1929 bool fill_with_hole) { 1942 bool fill_with_hole) {
1930 HValue* context = builder()->environment()->LookupContext(); 1943 // These HForceRepresentations are because we store these as fields in the
1931 1944 // objects we construct, and an int32-to-smi HChange could deopt. Accept
1945 // the deopt possibility now, before allocation occurs.
1946 capacity = builder()->Add<HForceRepresentation>(capacity,
1947 Representation::Smi());
1948 length_field = builder()->Add<HForceRepresentation>(length_field,
1949 Representation::Smi());
1932 // Allocate (dealing with failure appropriately) 1950 // Allocate (dealing with failure appropriately)
1933 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); 1951 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes,
1934 HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes, 1952 HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE);
1935 HType::JSArray(), flags);
1936 1953
1937 // Fill in the fields: map, properties, length 1954 // Fill in the fields: map, properties, length
1938 HValue* map; 1955 HValue* map;
1939 if (allocation_site_payload_ == NULL) { 1956 if (allocation_site_payload_ == NULL) {
1940 map = EmitInternalMapCode(); 1957 map = EmitInternalMapCode();
1941 } else { 1958 } else {
1942 map = EmitMapCode(context); 1959 map = EmitMapCode();
1943 } 1960 }
1944 elements_location_ = builder()->BuildJSArrayHeader(new_object, 1961 elements_location_ = builder()->BuildJSArrayHeader(new_object,
1945 map, 1962 map,
1946 mode_, 1963 mode_,
1947 kind_, 1964 kind_,
1948 allocation_site_payload_, 1965 allocation_site_payload_,
1949 length_field); 1966 length_field);
1950 1967
1951 // Initialize the elements 1968 // Initialize the elements
1952 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); 1969 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
1953 1970
1954 if (fill_with_hole) { 1971 if (fill_with_hole) {
1955 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, 1972 builder()->BuildFillElementsWithHole(elements_location_, kind_,
1956 graph()->GetConstant0(), capacity); 1973 graph()->GetConstant0(), capacity);
1957 } 1974 }
1958 1975
1959 return new_object; 1976 return new_object;
1960 } 1977 }
1961 1978
1962 1979
1963 HStoreNamedField* HGraphBuilder::AddStore(HValue *object,
1964 HObjectAccess access,
1965 HValue *val) {
1966 return Add<HStoreNamedField>(object, access, val);
1967 }
1968
1969
1970 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object,
1971 HObjectAccess access,
1972 HValue *typecheck) {
1973 return Add<HLoadNamedField>(object, access, typecheck);
1974 }
1975
1976
1977 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, 1980 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
1978 Handle<Map> map) { 1981 Handle<Map> map) {
1979 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), 1982 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
1980 Add<HConstant>(map)); 1983 Add<HConstant>(map));
1981 } 1984 }
1982 1985
1983 1986
1984 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin, 1987 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
1985 HValue* context) { 1988 HGlobalObject* global_object = Add<HGlobalObject>();
1986 HGlobalObject* global_object = Add<HGlobalObject>(context);
1987 HObjectAccess access = HObjectAccess::ForJSObjectOffset( 1989 HObjectAccess access = HObjectAccess::ForJSObjectOffset(
1988 GlobalObject::kBuiltinsOffset); 1990 GlobalObject::kBuiltinsOffset);
1989 HValue* builtins = AddLoad(global_object, access); 1991 HValue* builtins = Add<HLoadNamedField>(global_object, access);
1990 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( 1992 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset(
1991 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); 1993 JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
1992 return AddLoad(builtins, function_access); 1994 return Add<HLoadNamedField>(builtins, function_access);
1993 } 1995 }
1994 1996
1995 1997
1996 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) 1998 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
1997 : HGraphBuilder(info), 1999 : HGraphBuilder(info),
1998 function_state_(NULL), 2000 function_state_(NULL),
1999 initial_function_state_(this, info, NORMAL_RETURN), 2001 initial_function_state_(this, info, NORMAL_RETURN),
2000 ast_context_(NULL), 2002 ast_context_(NULL),
2001 break_scope_(NULL), 2003 break_scope_(NULL),
2002 inlined_count_(0), 2004 inlined_count_(0),
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
2480 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone()); 2482 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
2481 for (int i = 0; i < block_count; ++i) { 2483 for (int i = 0; i < block_count; ++i) {
2482 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 2484 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
2483 HPhi* phi = blocks_[i]->phis()->at(j); 2485 HPhi* phi = blocks_[i]->phis()->at(j);
2484 phi_list_->Add(phi, zone()); 2486 phi_list_->Add(phi, zone());
2485 } 2487 }
2486 } 2488 }
2487 } 2489 }
2488 2490
2489 2491
2490 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
2491 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return;
2492 phi->ClearFlag(HValue::kAllowUndefinedAsNaN);
2493 for (int i = 0; i < phi->OperandCount(); ++i) {
2494 HValue* input = phi->OperandAt(i);
2495 if (input->IsPhi()) {
2496 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
2497 }
2498 }
2499 }
2500
2501
2502 void HGraph::MarkDeoptimizeOnUndefined() {
2503 HPhase phase("H_MarkDeoptimizeOnUndefined", this);
2504 // Compute DeoptimizeOnUndefined flag for phis. Any phi that can reach a use
2505 // with DeoptimizeOnUndefined set must have DeoptimizeOnUndefined set.
2506 // Currently only HCompareNumericAndBranch, with double input representation,
2507 // has this flag set. The flag is used by HChange tagged->double, which must
2508 // deoptimize if one of its uses has this flag set.
2509 for (int i = 0; i < phi_list()->length(); i++) {
2510 HPhi* phi = phi_list()->at(i);
2511 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
2512 HValue* use_value = it.value();
2513 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
2514 RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
2515 break;
2516 }
2517 }
2518 }
2519 }
2520
2521
2522 // Implementation of utility class to encapsulate the translation state for 2492 // Implementation of utility class to encapsulate the translation state for
2523 // a (possibly inlined) function. 2493 // a (possibly inlined) function.
2524 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, 2494 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
2525 CompilationInfo* info, 2495 CompilationInfo* info,
2526 InliningKind inlining_kind) 2496 InliningKind inlining_kind)
2527 : owner_(owner), 2497 : owner_(owner),
2528 compilation_info_(info), 2498 compilation_info_(info),
2529 call_context_(NULL), 2499 call_context_(NULL),
2530 inlining_kind_(inlining_kind), 2500 inlining_kind_(inlining_kind),
2531 function_return_(NULL), 2501 function_return_(NULL),
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2603 2573
2604 void EffectContext::ReturnValue(HValue* value) { 2574 void EffectContext::ReturnValue(HValue* value) {
2605 // The value is simply ignored. 2575 // The value is simply ignored.
2606 } 2576 }
2607 2577
2608 2578
2609 void ValueContext::ReturnValue(HValue* value) { 2579 void ValueContext::ReturnValue(HValue* value) {
2610 // The value is tracked in the bailout environment, and communicated 2580 // The value is tracked in the bailout environment, and communicated
2611 // through the environment as the result of the expression. 2581 // through the environment as the result of the expression.
2612 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { 2582 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
2613 owner()->Bailout("bad value context for arguments value"); 2583 owner()->Bailout(kBadValueContextForArgumentsValue);
2614 } 2584 }
2615 owner()->Push(value); 2585 owner()->Push(value);
2616 } 2586 }
2617 2587
2618 2588
2619 void TestContext::ReturnValue(HValue* value) { 2589 void TestContext::ReturnValue(HValue* value) {
2620 BuildBranch(value); 2590 BuildBranch(value);
2621 } 2591 }
2622 2592
2623 2593
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2655 } else { 2625 } else {
2656 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); 2626 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
2657 owner()->set_current_block(join); 2627 owner()->set_current_block(join);
2658 } 2628 }
2659 } 2629 }
2660 2630
2661 2631
2662 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { 2632 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
2663 ASSERT(!instr->IsControlInstruction()); 2633 ASSERT(!instr->IsControlInstruction());
2664 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { 2634 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
2665 return owner()->Bailout("bad value context for arguments object value"); 2635 return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
2666 } 2636 }
2667 owner()->AddInstruction(instr); 2637 owner()->AddInstruction(instr);
2668 owner()->Push(instr); 2638 owner()->Push(instr);
2669 if (instr->HasObservableSideEffects()) { 2639 if (instr->HasObservableSideEffects()) {
2670 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 2640 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
2671 } 2641 }
2672 } 2642 }
2673 2643
2674 2644
2675 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { 2645 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
2676 ASSERT(!instr->HasObservableSideEffects()); 2646 ASSERT(!instr->HasObservableSideEffects());
2677 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { 2647 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
2678 return owner()->Bailout("bad value context for arguments object value"); 2648 return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
2679 } 2649 }
2680 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); 2650 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
2681 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); 2651 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
2682 instr->SetSuccessorAt(0, materialize_true); 2652 instr->SetSuccessorAt(0, materialize_true);
2683 instr->SetSuccessorAt(1, materialize_false); 2653 instr->SetSuccessorAt(1, materialize_false);
2684 owner()->current_block()->Finish(instr); 2654 owner()->current_block()->Finish(instr);
2685 owner()->set_current_block(materialize_true); 2655 owner()->set_current_block(materialize_true);
2686 owner()->Push(owner()->graph()->GetConstantTrue()); 2656 owner()->Push(owner()->graph()->GetConstantTrue());
2687 owner()->set_current_block(materialize_false); 2657 owner()->set_current_block(materialize_false);
2688 owner()->Push(owner()->graph()->GetConstantFalse()); 2658 owner()->Push(owner()->graph()->GetConstantFalse());
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2758 } 2728 }
2759 2729
2760 2730
2761 void TestContext::BuildBranch(HValue* value) { 2731 void TestContext::BuildBranch(HValue* value) {
2762 // We expect the graph to be in edge-split form: there is no edge that 2732 // We expect the graph to be in edge-split form: there is no edge that
2763 // connects a branch node to a join node. We conservatively ensure that 2733 // connects a branch node to a join node. We conservatively ensure that
2764 // property by always adding an empty block on the outgoing edges of this 2734 // property by always adding an empty block on the outgoing edges of this
2765 // branch. 2735 // branch.
2766 HOptimizedGraphBuilder* builder = owner(); 2736 HOptimizedGraphBuilder* builder = owner();
2767 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2737 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2768 builder->Bailout("arguments object value in a test context"); 2738 builder->Bailout(kArgumentsObjectValueInATestContext);
2769 } 2739 }
2770 if (value->IsConstant()) { 2740 if (value->IsConstant()) {
2771 HConstant* constant_value = HConstant::cast(value); 2741 HConstant* constant_value = HConstant::cast(value);
2772 if (constant_value->BooleanValue()) { 2742 if (constant_value->BooleanValue()) {
2773 builder->current_block()->Goto(if_true(), builder->function_state()); 2743 builder->current_block()->Goto(if_true(), builder->function_state());
2774 } else { 2744 } else {
2775 builder->current_block()->Goto(if_false(), builder->function_state()); 2745 builder->current_block()->Goto(if_false(), builder->function_state());
2776 } 2746 }
2777 builder->set_current_block(NULL); 2747 builder->set_current_block(NULL);
2778 return; 2748 return;
(...skipping 25 matching lines...) Expand all
2804 } while (false) 2774 } while (false)
2805 2775
2806 2776
2807 #define CHECK_ALIVE_OR_RETURN(call, value) \ 2777 #define CHECK_ALIVE_OR_RETURN(call, value) \
2808 do { \ 2778 do { \
2809 call; \ 2779 call; \
2810 if (HasStackOverflow() || current_block() == NULL) return value; \ 2780 if (HasStackOverflow() || current_block() == NULL) return value; \
2811 } while (false) 2781 } while (false)
2812 2782
2813 2783
2814 void HOptimizedGraphBuilder::Bailout(const char* reason) { 2784 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
2815 current_info()->set_bailout_reason(reason); 2785 current_info()->set_bailout_reason(reason);
2816 SetStackOverflow(); 2786 SetStackOverflow();
2817 } 2787 }
2818 2788
2819 2789
2820 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { 2790 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
2821 EffectContext for_effect(this); 2791 EffectContext for_effect(this);
2822 Visit(expr); 2792 Visit(expr);
2823 } 2793 }
2824 2794
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2863 void HOptimizedGraphBuilder::VisitExpressions( 2833 void HOptimizedGraphBuilder::VisitExpressions(
2864 ZoneList<Expression*>* exprs) { 2834 ZoneList<Expression*>* exprs) {
2865 for (int i = 0; i < exprs->length(); ++i) { 2835 for (int i = 0; i < exprs->length(); ++i) {
2866 CHECK_ALIVE(VisitForValue(exprs->at(i))); 2836 CHECK_ALIVE(VisitForValue(exprs->at(i)));
2867 } 2837 }
2868 } 2838 }
2869 2839
2870 2840
2871 bool HOptimizedGraphBuilder::BuildGraph() { 2841 bool HOptimizedGraphBuilder::BuildGraph() {
2872 if (current_info()->function()->is_generator()) { 2842 if (current_info()->function()->is_generator()) {
2873 Bailout("function is a generator"); 2843 Bailout(kFunctionIsAGenerator);
2874 return false; 2844 return false;
2875 } 2845 }
2876 Scope* scope = current_info()->scope(); 2846 Scope* scope = current_info()->scope();
2877 if (scope->HasIllegalRedeclaration()) { 2847 if (scope->HasIllegalRedeclaration()) {
2878 Bailout("function with illegal redeclaration"); 2848 Bailout(kFunctionWithIllegalRedeclaration);
2879 return false; 2849 return false;
2880 } 2850 }
2881 if (scope->calls_eval()) { 2851 if (scope->calls_eval()) {
2882 Bailout("function calls eval"); 2852 Bailout(kFunctionCallsEval);
2883 return false; 2853 return false;
2884 } 2854 }
2885 SetUpScope(scope); 2855 SetUpScope(scope);
2886 2856
2887 // Add an edge to the body entry. This is warty: the graph's start 2857 // Add an edge to the body entry. This is warty: the graph's start
2888 // environment will be used by the Lithium translation as the initial 2858 // environment will be used by the Lithium translation as the initial
2889 // environment on graph entry, but it has now been mutated by the 2859 // environment on graph entry, but it has now been mutated by the
2890 // Hydrogen translation of the instructions in the start block. This 2860 // Hydrogen translation of the instructions in the start block. This
2891 // environment uses values which have not been defined yet. These 2861 // environment uses values which have not been defined yet. These
2892 // Hydrogen instructions will then be replayed by the Lithium 2862 // Hydrogen instructions will then be replayed by the Lithium
(...skipping 13 matching lines...) Expand all
2906 set_current_block(body_entry); 2876 set_current_block(body_entry);
2907 2877
2908 // Handle implicit declaration of the function name in named function 2878 // Handle implicit declaration of the function name in named function
2909 // expressions before other declarations. 2879 // expressions before other declarations.
2910 if (scope->is_function_scope() && scope->function() != NULL) { 2880 if (scope->is_function_scope() && scope->function() != NULL) {
2911 VisitVariableDeclaration(scope->function()); 2881 VisitVariableDeclaration(scope->function());
2912 } 2882 }
2913 VisitDeclarations(scope->declarations()); 2883 VisitDeclarations(scope->declarations());
2914 Add<HSimulate>(BailoutId::Declarations()); 2884 Add<HSimulate>(BailoutId::Declarations());
2915 2885
2916 HValue* context = environment()->LookupContext(); 2886 HValue* context = environment()->context();
2917 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); 2887 Add<HStackCheck>(context, HStackCheck::kFunctionEntry);
2918 2888
2919 VisitStatements(current_info()->function()->body()); 2889 VisitStatements(current_info()->function()->body());
2920 if (HasStackOverflow()) return false; 2890 if (HasStackOverflow()) return false;
2921 2891
2922 if (current_block() != NULL) { 2892 if (current_block() != NULL) {
2923 Add<HReturn>(graph()->GetConstantUndefined()); 2893 Add<HReturn>(graph()->GetConstantUndefined());
2924 set_current_block(NULL); 2894 set_current_block(NULL);
2925 } 2895 }
2926 2896
(...skipping 11 matching lines...) Expand all
2938 !type_info->matches_inlined_type_change_checksum(composite_checksum)); 2908 !type_info->matches_inlined_type_change_checksum(composite_checksum));
2939 type_info->set_inlined_type_change_checksum(composite_checksum); 2909 type_info->set_inlined_type_change_checksum(composite_checksum);
2940 2910
2941 // Perform any necessary OSR-specific cleanups or changes to the graph. 2911 // Perform any necessary OSR-specific cleanups or changes to the graph.
2942 osr_->FinishGraph(); 2912 osr_->FinishGraph();
2943 2913
2944 return true; 2914 return true;
2945 } 2915 }
2946 2916
2947 2917
2948 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { 2918 bool HGraph::Optimize(BailoutReason* bailout_reason) {
2949 *bailout_reason = SmartArrayPointer<char>();
2950 OrderBlocks(); 2919 OrderBlocks();
2951 AssignDominators(); 2920 AssignDominators();
2952 2921
2953 // We need to create a HConstant "zero" now so that GVN will fold every 2922 // We need to create a HConstant "zero" now so that GVN will fold every
2954 // zero-valued constant in the graph together. 2923 // zero-valued constant in the graph together.
2955 // The constant is needed to make idef-based bounds check work: the pass 2924 // The constant is needed to make idef-based bounds check work: the pass
2956 // evaluates relations with "zero" and that zero cannot be created after GVN. 2925 // evaluates relations with "zero" and that zero cannot be created after GVN.
2957 GetConstant0(); 2926 GetConstant0();
2958 2927
2959 #ifdef DEBUG 2928 #ifdef DEBUG
2960 // Do a full verify after building the graph and computing dominators. 2929 // Do a full verify after building the graph and computing dominators.
2961 Verify(true); 2930 Verify(true);
2962 #endif 2931 #endif
2963 2932
2964 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { 2933 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
2965 Run<HEnvironmentLivenessAnalysisPhase>(); 2934 Run<HEnvironmentLivenessAnalysisPhase>();
2966 } 2935 }
2967 2936
2968 Run<HPropagateDeoptimizingMarkPhase>(); 2937 Run<HPropagateDeoptimizingMarkPhase>();
2969 if (!CheckConstPhiUses()) { 2938 if (!CheckConstPhiUses()) {
2970 *bailout_reason = SmartArrayPointer<char>(StrDup( 2939 *bailout_reason = kUnsupportedPhiUseOfConstVariable;
2971 "Unsupported phi use of const variable"));
2972 return false; 2940 return false;
2973 } 2941 }
2974 Run<HRedundantPhiEliminationPhase>(); 2942 Run<HRedundantPhiEliminationPhase>();
2975 if (!CheckArgumentsPhiUses()) { 2943 if (!CheckArgumentsPhiUses()) {
2976 *bailout_reason = SmartArrayPointer<char>(StrDup( 2944 *bailout_reason = kUnsupportedPhiUseOfArguments;
2977 "Unsupported phi use of arguments"));
2978 return false; 2945 return false;
2979 } 2946 }
2980 2947
2981 // Remove dead code and phis 2948 // Remove dead code and phis
2982 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); 2949 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
2983 CollectPhis(); 2950 CollectPhis();
2984 2951
2985 if (has_osr()) osr()->FinishOsrValues(); 2952 if (has_osr()) osr()->FinishOsrValues();
2986 2953
2987 Run<HInferRepresentationPhase>(); 2954 Run<HInferRepresentationPhase>();
2988 2955
2989 // Remove HSimulate instructions that have turned out not to be needed 2956 // Remove HSimulate instructions that have turned out not to be needed
2990 // after all by folding them into the following HSimulate. 2957 // after all by folding them into the following HSimulate.
2991 // This must happen after inferring representations. 2958 // This must happen after inferring representations.
2992 Run<HMergeRemovableSimulatesPhase>(); 2959 Run<HMergeRemovableSimulatesPhase>();
2993 2960
2994 MarkDeoptimizeOnUndefined(); 2961 Run<HMarkDeoptimizeOnUndefinedPhase>();
2995 Run<HRepresentationChangesPhase>(); 2962 Run<HRepresentationChangesPhase>();
2996 2963
2997 Run<HInferTypesPhase>(); 2964 Run<HInferTypesPhase>();
2998 2965
2999 // Must be performed before canonicalization to ensure that Canonicalize 2966 // Must be performed before canonicalization to ensure that Canonicalize
3000 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with 2967 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
3001 // zero. 2968 // zero.
3002 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); 2969 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
3003 2970
3004 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); 2971 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
3117 } 3084 }
3118 3085
3119 while (!arguments.is_empty()) { 3086 while (!arguments.is_empty()) {
3120 Add<HPushArgument>(arguments.RemoveLast()); 3087 Add<HPushArgument>(arguments.RemoveLast());
3121 } 3088 }
3122 return call; 3089 return call;
3123 } 3090 }
3124 3091
3125 3092
3126 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { 3093 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
3127 HConstant* undefined_constant = Add<HConstant>( 3094 // First special is HContext.
3128 isolate()->factory()->undefined_value()); 3095 HInstruction* context = Add<HContext>();
3096 environment()->BindContext(context);
3097
3098 HConstant* undefined_constant = HConstant::cast(Add<HConstant>(
3099 isolate()->factory()->undefined_value()));
3129 graph()->set_undefined_constant(undefined_constant); 3100 graph()->set_undefined_constant(undefined_constant);
3130 3101
3131 // Create an arguments object containing the initial parameters. Set the 3102 // Create an arguments object containing the initial parameters. Set the
3132 // initial values of parameters including "this" having parameter index 0. 3103 // initial values of parameters including "this" having parameter index 0.
3133 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); 3104 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
3134 HArgumentsObject* arguments_object = 3105 HArgumentsObject* arguments_object =
3135 new(zone()) HArgumentsObject(environment()->parameter_count(), zone()); 3106 New<HArgumentsObject>(environment()->parameter_count());
3136 for (int i = 0; i < environment()->parameter_count(); ++i) { 3107 for (int i = 0; i < environment()->parameter_count(); ++i) {
3137 HInstruction* parameter = Add<HParameter>(i); 3108 HInstruction* parameter = Add<HParameter>(i);
3138 arguments_object->AddArgument(parameter, zone()); 3109 arguments_object->AddArgument(parameter, zone());
3139 environment()->Bind(i, parameter); 3110 environment()->Bind(i, parameter);
3140 } 3111 }
3141 AddInstruction(arguments_object); 3112 AddInstruction(arguments_object);
3142 graph()->SetArgumentsObject(arguments_object); 3113 graph()->SetArgumentsObject(arguments_object);
3143 3114
3144 // First special is HContext.
3145 HInstruction* context = Add<HContext>();
3146 environment()->BindContext(context);
3147
3148 // Initialize specials and locals to undefined. 3115 // Initialize specials and locals to undefined.
3149 for (int i = environment()->parameter_count() + 1; 3116 for (int i = environment()->parameter_count() + 1;
3150 i < environment()->length(); 3117 i < environment()->length();
3151 ++i) { 3118 ++i) {
3152 environment()->Bind(i, undefined_constant); 3119 environment()->Bind(i, undefined_constant);
3153 } 3120 }
3154 3121
3155 // Handle the arguments and arguments shadow variables specially (they do 3122 // Handle the arguments and arguments shadow variables specially (they do
3156 // not have declarations). 3123 // not have declarations).
3157 if (scope->arguments() != NULL) { 3124 if (scope->arguments() != NULL) {
3158 if (!scope->arguments()->IsStackAllocated()) { 3125 if (!scope->arguments()->IsStackAllocated()) {
3159 return Bailout("context-allocated arguments"); 3126 return Bailout(kContextAllocatedArguments);
3160 } 3127 }
3161 3128
3162 environment()->Bind(scope->arguments(), 3129 environment()->Bind(scope->arguments(),
3163 graph()->GetArgumentsObject()); 3130 graph()->GetArgumentsObject());
3164 } 3131 }
3165 } 3132 }
3166 3133
3167 3134
3168 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 3135 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
3169 for (int i = 0; i < statements->length(); i++) { 3136 for (int i = 0; i < statements->length(); i++) {
3170 CHECK_ALIVE(Visit(statements->at(i))); 3137 CHECK_ALIVE(Visit(statements->at(i)));
3171 } 3138 }
3172 } 3139 }
3173 3140
3174 3141
3175 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { 3142 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
3176 ASSERT(!HasStackOverflow()); 3143 ASSERT(!HasStackOverflow());
3177 ASSERT(current_block() != NULL); 3144 ASSERT(current_block() != NULL);
3178 ASSERT(current_block()->HasPredecessor()); 3145 ASSERT(current_block()->HasPredecessor());
3179 if (stmt->scope() != NULL) { 3146 if (stmt->scope() != NULL) {
3180 return Bailout("ScopedBlock"); 3147 return Bailout(kScopedBlock);
3181 } 3148 }
3182 BreakAndContinueInfo break_info(stmt); 3149 BreakAndContinueInfo break_info(stmt);
3183 { BreakAndContinueScope push(&break_info, this); 3150 { BreakAndContinueScope push(&break_info, this);
3184 CHECK_BAILOUT(VisitStatements(stmt->statements())); 3151 CHECK_BAILOUT(VisitStatements(stmt->statements()));
3185 } 3152 }
3186 HBasicBlock* break_block = break_info.break_block(); 3153 HBasicBlock* break_block = break_info.break_block();
3187 if (break_block != NULL) { 3154 if (break_block != NULL) {
3188 if (current_block() != NULL) current_block()->Goto(break_block); 3155 if (current_block() != NULL) current_block()->Goto(break_block);
3189 break_block->SetJoinId(stmt->ExitId()); 3156 break_block->SetJoinId(stmt->ExitId());
3190 set_current_block(break_block); 3157 set_current_block(break_block);
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
3382 } 3349 }
3383 } 3350 }
3384 set_current_block(NULL); 3351 set_current_block(NULL);
3385 } 3352 }
3386 3353
3387 3354
3388 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { 3355 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
3389 ASSERT(!HasStackOverflow()); 3356 ASSERT(!HasStackOverflow());
3390 ASSERT(current_block() != NULL); 3357 ASSERT(current_block() != NULL);
3391 ASSERT(current_block()->HasPredecessor()); 3358 ASSERT(current_block()->HasPredecessor());
3392 return Bailout("WithStatement"); 3359 return Bailout(kWithStatement);
3393 } 3360 }
3394 3361
3395 3362
3396 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 3363 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
3397 ASSERT(!HasStackOverflow()); 3364 ASSERT(!HasStackOverflow());
3398 ASSERT(current_block() != NULL); 3365 ASSERT(current_block() != NULL);
3399 ASSERT(current_block()->HasPredecessor()); 3366 ASSERT(current_block()->HasPredecessor());
3400 3367
3401 // We only optimize switch statements with smi-literal smi comparisons, 3368 // We only optimize switch statements with smi-literal smi comparisons,
3402 // with a bounded number of clauses. 3369 // with a bounded number of clauses.
3403 const int kCaseClauseLimit = 128; 3370 const int kCaseClauseLimit = 128;
3404 ZoneList<CaseClause*>* clauses = stmt->cases(); 3371 ZoneList<CaseClause*>* clauses = stmt->cases();
3405 int clause_count = clauses->length(); 3372 int clause_count = clauses->length();
3406 if (clause_count > kCaseClauseLimit) { 3373 if (clause_count > kCaseClauseLimit) {
3407 return Bailout("SwitchStatement: too many clauses"); 3374 return Bailout(kSwitchStatementTooManyClauses);
3408 } 3375 }
3409 3376
3410 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); 3377 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
3411 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { 3378 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) {
3412 return Bailout("SwitchStatement: mixed or non-literal switch labels"); 3379 return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels);
3413 } 3380 }
3414 3381
3415 HValue* context = environment()->LookupContext(); 3382 HValue* context = environment()->context();
3416 3383
3417 CHECK_ALIVE(VisitForValue(stmt->tag())); 3384 CHECK_ALIVE(VisitForValue(stmt->tag()));
3418 Add<HSimulate>(stmt->EntryId()); 3385 Add<HSimulate>(stmt->EntryId());
3419 HValue* tag_value = Pop(); 3386 HValue* tag_value = Pop();
3420 HBasicBlock* first_test_block = current_block(); 3387 HBasicBlock* first_test_block = current_block();
3421 3388
3422 HUnaryControlInstruction* string_check = NULL; 3389 HUnaryControlInstruction* string_check = NULL;
3423 HBasicBlock* not_string_block = NULL; 3390 HBasicBlock* not_string_block = NULL;
3424 3391
3425 // Test switch's tag value if all clauses are string literals 3392 // Test switch's tag value if all clauses are string literals
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
3553 set_current_block(break_block); 3520 set_current_block(break_block);
3554 } 3521 }
3555 } 3522 }
3556 3523
3557 3524
3558 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, 3525 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
3559 HBasicBlock* loop_entry, 3526 HBasicBlock* loop_entry,
3560 BreakAndContinueInfo* break_info) { 3527 BreakAndContinueInfo* break_info) {
3561 BreakAndContinueScope push(break_info, this); 3528 BreakAndContinueScope push(break_info, this);
3562 Add<HSimulate>(stmt->StackCheckId()); 3529 Add<HSimulate>(stmt->StackCheckId());
3563 HValue* context = environment()->LookupContext(); 3530 HValue* context = environment()->context();
3564 HStackCheck* stack_check = Add<HStackCheck>( 3531 HStackCheck* stack_check = HStackCheck::cast(Add<HStackCheck>(
3565 context, HStackCheck::kBackwardsBranch); 3532 context, HStackCheck::kBackwardsBranch));
3566 ASSERT(loop_entry->IsLoopHeader()); 3533 ASSERT(loop_entry->IsLoopHeader());
3567 loop_entry->loop_information()->set_stack_check(stack_check); 3534 loop_entry->loop_information()->set_stack_check(stack_check);
3568 CHECK_BAILOUT(Visit(stmt->body())); 3535 CHECK_BAILOUT(Visit(stmt->body()));
3569 } 3536 }
3570 3537
3571 3538
3572 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 3539 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
3573 ASSERT(!HasStackOverflow()); 3540 ASSERT(!HasStackOverflow());
3574 ASSERT(current_block() != NULL); 3541 ASSERT(current_block() != NULL);
3575 ASSERT(current_block()->HasPredecessor()); 3542 ASSERT(current_block()->HasPredecessor());
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
3694 set_current_block(loop_exit); 3661 set_current_block(loop_exit);
3695 } 3662 }
3696 3663
3697 3664
3698 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 3665 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
3699 ASSERT(!HasStackOverflow()); 3666 ASSERT(!HasStackOverflow());
3700 ASSERT(current_block() != NULL); 3667 ASSERT(current_block() != NULL);
3701 ASSERT(current_block()->HasPredecessor()); 3668 ASSERT(current_block()->HasPredecessor());
3702 3669
3703 if (!FLAG_optimize_for_in) { 3670 if (!FLAG_optimize_for_in) {
3704 return Bailout("ForInStatement optimization is disabled"); 3671 return Bailout(kForInStatementOptimizationIsDisabled);
3705 } 3672 }
3706 3673
3707 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { 3674 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
3708 return Bailout("ForInStatement is not fast case"); 3675 return Bailout(kForInStatementIsNotFastCase);
3709 } 3676 }
3710 3677
3711 if (!stmt->each()->IsVariableProxy() || 3678 if (!stmt->each()->IsVariableProxy() ||
3712 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { 3679 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
3713 return Bailout("ForInStatement with non-local each variable"); 3680 return Bailout(kForInStatementWithNonLocalEachVariable);
3714 } 3681 }
3715 3682
3716 Variable* each_var = stmt->each()->AsVariableProxy()->var(); 3683 Variable* each_var = stmt->each()->AsVariableProxy()->var();
3717 3684
3718 CHECK_ALIVE(VisitForValue(stmt->enumerable())); 3685 CHECK_ALIVE(VisitForValue(stmt->enumerable()));
3719 HValue* enumerable = Top(); // Leave enumerable at the top. 3686 HValue* enumerable = Top(); // Leave enumerable at the top.
3720 3687
3721 HInstruction* map = Add<HForInPrepareMap>( 3688 HInstruction* map = Add<HForInPrepareMap>(enumerable);
3722 environment()->LookupContext(), enumerable);
3723 Add<HSimulate>(stmt->PrepareId()); 3689 Add<HSimulate>(stmt->PrepareId());
3724 3690
3725 HInstruction* array = Add<HForInCacheArray>( 3691 HInstruction* array = Add<HForInCacheArray>(
3726 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); 3692 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
3727 3693
3728 HInstruction* enum_length = Add<HMapEnumLength>(map); 3694 HInstruction* enum_length = Add<HMapEnumLength>(map);
3729 3695
3730 HInstruction* start_index = Add<HConstant>(0); 3696 HInstruction* start_index = Add<HConstant>(0);
3731 3697
3732 Push(map); 3698 Push(map);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3778 BreakAndContinueInfo break_info(stmt, 5); 3744 BreakAndContinueInfo break_info(stmt, 5);
3779 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 3745 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
3780 3746
3781 HBasicBlock* body_exit = 3747 HBasicBlock* body_exit =
3782 JoinContinue(stmt, current_block(), break_info.continue_block()); 3748 JoinContinue(stmt, current_block(), break_info.continue_block());
3783 3749
3784 if (body_exit != NULL) { 3750 if (body_exit != NULL) {
3785 set_current_block(body_exit); 3751 set_current_block(body_exit);
3786 3752
3787 HValue* current_index = Pop(); 3753 HValue* current_index = Pop();
3788 HInstruction* new_index = HAdd::New(zone(), 3754 HInstruction* new_index = New<HAdd>(current_index,
3789 environment()->LookupContext(),
3790 current_index,
3791 graph()->GetConstant1()); 3755 graph()->GetConstant1());
3792 PushAndAdd(new_index); 3756 PushAndAdd(new_index);
3793 body_exit = current_block(); 3757 body_exit = current_block();
3794 } 3758 }
3795 3759
3796 HBasicBlock* loop_exit = CreateLoop(stmt, 3760 HBasicBlock* loop_exit = CreateLoop(stmt,
3797 loop_entry, 3761 loop_entry,
3798 body_exit, 3762 body_exit,
3799 loop_successor, 3763 loop_successor,
3800 break_info.break_block()); 3764 break_info.break_block());
3801 3765
3802 set_current_block(loop_exit); 3766 set_current_block(loop_exit);
3803 } 3767 }
3804 3768
3805 3769
3806 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { 3770 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
3807 ASSERT(!HasStackOverflow()); 3771 ASSERT(!HasStackOverflow());
3808 ASSERT(current_block() != NULL); 3772 ASSERT(current_block() != NULL);
3809 ASSERT(current_block()->HasPredecessor()); 3773 ASSERT(current_block()->HasPredecessor());
3810 return Bailout("ForOfStatement"); 3774 return Bailout(kForOfStatement);
3811 } 3775 }
3812 3776
3813 3777
3814 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 3778 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
3815 ASSERT(!HasStackOverflow()); 3779 ASSERT(!HasStackOverflow());
3816 ASSERT(current_block() != NULL); 3780 ASSERT(current_block() != NULL);
3817 ASSERT(current_block()->HasPredecessor()); 3781 ASSERT(current_block()->HasPredecessor());
3818 return Bailout("TryCatchStatement"); 3782 return Bailout(kTryCatchStatement);
3819 } 3783 }
3820 3784
3821 3785
3822 void HOptimizedGraphBuilder::VisitTryFinallyStatement( 3786 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
3823 TryFinallyStatement* stmt) { 3787 TryFinallyStatement* stmt) {
3824 ASSERT(!HasStackOverflow()); 3788 ASSERT(!HasStackOverflow());
3825 ASSERT(current_block() != NULL); 3789 ASSERT(current_block() != NULL);
3826 ASSERT(current_block()->HasPredecessor()); 3790 ASSERT(current_block()->HasPredecessor());
3827 return Bailout("TryFinallyStatement"); 3791 return Bailout(kTryFinallyStatement);
3828 } 3792 }
3829 3793
3830 3794
3831 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 3795 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
3832 ASSERT(!HasStackOverflow()); 3796 ASSERT(!HasStackOverflow());
3833 ASSERT(current_block() != NULL); 3797 ASSERT(current_block() != NULL);
3834 ASSERT(current_block()->HasPredecessor()); 3798 ASSERT(current_block()->HasPredecessor());
3835 return Bailout("DebuggerStatement"); 3799 return Bailout(kDebuggerStatement);
3836 } 3800 }
3837 3801
3838 3802
3839 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( 3803 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo(
3840 Code* unoptimized_code, FunctionLiteral* expr) { 3804 Code* unoptimized_code, FunctionLiteral* expr) {
3841 int start_position = expr->start_position(); 3805 int start_position = expr->start_position();
3842 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { 3806 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) {
3843 RelocInfo* rinfo = it.rinfo(); 3807 RelocInfo* rinfo = it.rinfo();
3844 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; 3808 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
3845 Object* obj = rinfo->target_object(); 3809 Object* obj = rinfo->target_object();
(...skipping 13 matching lines...) Expand all
3859 ASSERT(!HasStackOverflow()); 3823 ASSERT(!HasStackOverflow());
3860 ASSERT(current_block() != NULL); 3824 ASSERT(current_block() != NULL);
3861 ASSERT(current_block()->HasPredecessor()); 3825 ASSERT(current_block()->HasPredecessor());
3862 Handle<SharedFunctionInfo> shared_info = 3826 Handle<SharedFunctionInfo> shared_info =
3863 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); 3827 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr);
3864 if (shared_info.is_null()) { 3828 if (shared_info.is_null()) {
3865 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); 3829 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script());
3866 } 3830 }
3867 // We also have a stack overflow if the recursive compilation did. 3831 // We also have a stack overflow if the recursive compilation did.
3868 if (HasStackOverflow()) return; 3832 if (HasStackOverflow()) return;
3869 HValue* context = environment()->LookupContext(); 3833 HValue* context = environment()->context();
3870 HFunctionLiteral* instr = 3834 HFunctionLiteral* instr =
3871 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); 3835 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
3872 return ast_context()->ReturnInstruction(instr, expr->id()); 3836 return ast_context()->ReturnInstruction(instr, expr->id());
3873 } 3837 }
3874 3838
3875 3839
3876 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( 3840 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral(
3877 SharedFunctionInfoLiteral* expr) { 3841 SharedFunctionInfoLiteral* expr) {
3878 ASSERT(!HasStackOverflow()); 3842 ASSERT(!HasStackOverflow());
3879 ASSERT(current_block() != NULL); 3843 ASSERT(current_block() != NULL);
3880 ASSERT(current_block()->HasPredecessor()); 3844 ASSERT(current_block()->HasPredecessor());
3881 return Bailout("SharedFunctionInfoLiteral"); 3845 return Bailout(kSharedFunctionInfoLiteral);
3882 } 3846 }
3883 3847
3884 3848
3885 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { 3849 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
3886 ASSERT(!HasStackOverflow()); 3850 ASSERT(!HasStackOverflow());
3887 ASSERT(current_block() != NULL); 3851 ASSERT(current_block() != NULL);
3888 ASSERT(current_block()->HasPredecessor()); 3852 ASSERT(current_block()->HasPredecessor());
3889 HBasicBlock* cond_true = graph()->CreateBasicBlock(); 3853 HBasicBlock* cond_true = graph()->CreateBasicBlock();
3890 HBasicBlock* cond_false = graph()->CreateBasicBlock(); 3854 HBasicBlock* cond_false = graph()->CreateBasicBlock();
3891 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); 3855 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3933 lookup->holder() != *global) { 3897 lookup->holder() != *global) {
3934 return kUseGeneric; 3898 return kUseGeneric;
3935 } 3899 }
3936 3900
3937 return kUseCell; 3901 return kUseCell;
3938 } 3902 }
3939 3903
3940 3904
3941 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { 3905 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
3942 ASSERT(var->IsContextSlot()); 3906 ASSERT(var->IsContextSlot());
3943 HValue* context = environment()->LookupContext(); 3907 HValue* context = environment()->context();
3944 int length = current_info()->scope()->ContextChainLength(var->scope()); 3908 int length = current_info()->scope()->ContextChainLength(var->scope());
3945 while (length-- > 0) { 3909 while (length-- > 0) {
3946 context = Add<HOuterContext>(context); 3910 context = Add<HOuterContext>(context);
3947 } 3911 }
3948 return context; 3912 return context;
3949 } 3913 }
3950 3914
3951 3915
3952 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 3916 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3953 ASSERT(!HasStackOverflow()); 3917 ASSERT(!HasStackOverflow());
3954 ASSERT(current_block() != NULL); 3918 ASSERT(current_block() != NULL);
3955 ASSERT(current_block()->HasPredecessor()); 3919 ASSERT(current_block()->HasPredecessor());
3956 Variable* variable = expr->var(); 3920 Variable* variable = expr->var();
3957 switch (variable->location()) { 3921 switch (variable->location()) {
3958 case Variable::UNALLOCATED: { 3922 case Variable::UNALLOCATED: {
3959 if (IsLexicalVariableMode(variable->mode())) { 3923 if (IsLexicalVariableMode(variable->mode())) {
3960 // TODO(rossberg): should this be an ASSERT? 3924 // TODO(rossberg): should this be an ASSERT?
3961 return Bailout("reference to global lexical variable"); 3925 return Bailout(kReferenceToGlobalLexicalVariable);
3962 } 3926 }
3963 // Handle known global constants like 'undefined' specially to avoid a 3927 // Handle known global constants like 'undefined' specially to avoid a
3964 // load from a global cell for them. 3928 // load from a global cell for them.
3965 Handle<Object> constant_value = 3929 Handle<Object> constant_value =
3966 isolate()->factory()->GlobalConstantFor(variable->name()); 3930 isolate()->factory()->GlobalConstantFor(variable->name());
3967 if (!constant_value.is_null()) { 3931 if (!constant_value.is_null()) {
3968 HConstant* instr = new(zone()) HConstant(constant_value); 3932 HConstant* instr = New<HConstant>(constant_value);
3969 return ast_context()->ReturnInstruction(instr, expr->id()); 3933 return ast_context()->ReturnInstruction(instr, expr->id());
3970 } 3934 }
3971 3935
3972 LookupResult lookup(isolate()); 3936 LookupResult lookup(isolate());
3973 GlobalPropertyAccess type = 3937 GlobalPropertyAccess type =
3974 LookupGlobalProperty(variable, &lookup, false); 3938 LookupGlobalProperty(variable, &lookup, false);
3975 3939
3976 if (type == kUseCell && 3940 if (type == kUseCell &&
3977 current_info()->global_object()->IsAccessCheckNeeded()) { 3941 current_info()->global_object()->IsAccessCheckNeeded()) {
3978 type = kUseGeneric; 3942 type = kUseGeneric;
3979 } 3943 }
3980 3944
3981 if (type == kUseCell) { 3945 if (type == kUseCell) {
3982 Handle<GlobalObject> global(current_info()->global_object()); 3946 Handle<GlobalObject> global(current_info()->global_object());
3983 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 3947 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
3984 if (cell->type()->IsConstant()) { 3948 if (cell->type()->IsConstant()) {
3985 cell->AddDependentCompilationInfo(top_info()); 3949 cell->AddDependentCompilationInfo(top_info());
3986 Handle<Object> constant_object = cell->type()->AsConstant(); 3950 Handle<Object> constant_object = cell->type()->AsConstant();
3987 if (constant_object->IsConsString()) { 3951 if (constant_object->IsConsString()) {
3988 constant_object = 3952 constant_object =
3989 FlattenGetString(Handle<String>::cast(constant_object)); 3953 FlattenGetString(Handle<String>::cast(constant_object));
3990 } 3954 }
3991 HConstant* constant = new(zone()) HConstant(constant_object); 3955 HConstant* constant = New<HConstant>(constant_object);
3992 return ast_context()->ReturnInstruction(constant, expr->id()); 3956 return ast_context()->ReturnInstruction(constant, expr->id());
3993 } else { 3957 } else {
3994 HLoadGlobalCell* instr = 3958 HLoadGlobalCell* instr =
3995 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); 3959 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
3996 return ast_context()->ReturnInstruction(instr, expr->id()); 3960 return ast_context()->ReturnInstruction(instr, expr->id());
3997 } 3961 }
3998 } else { 3962 } else {
3999 HValue* context = environment()->LookupContext(); 3963 HValue* context = environment()->context();
4000 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3964 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
4001 AddInstruction(global_object); 3965 AddInstruction(global_object);
4002 HLoadGlobalGeneric* instr = 3966 HLoadGlobalGeneric* instr =
4003 new(zone()) HLoadGlobalGeneric(context, 3967 new(zone()) HLoadGlobalGeneric(context,
4004 global_object, 3968 global_object,
4005 variable->name(), 3969 variable->name(),
4006 ast_context()->is_for_typeof()); 3970 ast_context()->is_for_typeof());
4007 instr->set_position(expr->position()); 3971 instr->set_position(expr->position());
4008 return ast_context()->ReturnInstruction(instr, expr->id()); 3972 return ast_context()->ReturnInstruction(instr, expr->id());
4009 } 3973 }
4010 } 3974 }
4011 3975
4012 case Variable::PARAMETER: 3976 case Variable::PARAMETER:
4013 case Variable::LOCAL: { 3977 case Variable::LOCAL: {
4014 HValue* value = LookupAndMakeLive(variable); 3978 HValue* value = LookupAndMakeLive(variable);
4015 if (value == graph()->GetConstantHole()) { 3979 if (value == graph()->GetConstantHole()) {
4016 ASSERT(IsDeclaredVariableMode(variable->mode()) && 3980 ASSERT(IsDeclaredVariableMode(variable->mode()) &&
4017 variable->mode() != VAR); 3981 variable->mode() != VAR);
4018 return Bailout("reference to uninitialized variable"); 3982 return Bailout(kReferenceToUninitializedVariable);
4019 } 3983 }
4020 return ast_context()->ReturnValue(value); 3984 return ast_context()->ReturnValue(value);
4021 } 3985 }
4022 3986
4023 case Variable::CONTEXT: { 3987 case Variable::CONTEXT: {
4024 HValue* context = BuildContextChainWalk(variable); 3988 HValue* context = BuildContextChainWalk(variable);
4025 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); 3989 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable);
4026 return ast_context()->ReturnInstruction(instr, expr->id()); 3990 return ast_context()->ReturnInstruction(instr, expr->id());
4027 } 3991 }
4028 3992
4029 case Variable::LOOKUP: 3993 case Variable::LOOKUP:
4030 return Bailout("reference to a variable which requires dynamic lookup"); 3994 return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
4031 } 3995 }
4032 } 3996 }
4033 3997
4034 3998
4035 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { 3999 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
4036 ASSERT(!HasStackOverflow()); 4000 ASSERT(!HasStackOverflow());
4037 ASSERT(current_block() != NULL); 4001 ASSERT(current_block() != NULL);
4038 ASSERT(current_block()->HasPredecessor()); 4002 ASSERT(current_block()->HasPredecessor());
4039 HConstant* instr = new(zone()) HConstant(expr->value()); 4003 HConstant* instr = New<HConstant>(expr->value());
4040 return ast_context()->ReturnInstruction(instr, expr->id()); 4004 return ast_context()->ReturnInstruction(instr, expr->id());
4041 } 4005 }
4042 4006
4043 4007
4044 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 4008 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
4045 ASSERT(!HasStackOverflow()); 4009 ASSERT(!HasStackOverflow());
4046 ASSERT(current_block() != NULL); 4010 ASSERT(current_block() != NULL);
4047 ASSERT(current_block()->HasPredecessor()); 4011 ASSERT(current_block()->HasPredecessor());
4048 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 4012 Handle<JSFunction> closure = function_state()->compilation_info()->closure();
4049 Handle<FixedArray> literals(closure->literals()); 4013 Handle<FixedArray> literals(closure->literals());
4050 HValue* context = environment()->LookupContext(); 4014 HValue* context = environment()->context();
4051 4015
4052 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, 4016 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
4053 literals, 4017 literals,
4054 expr->pattern(), 4018 expr->pattern(),
4055 expr->flags(), 4019 expr->flags(),
4056 expr->literal_index()); 4020 expr->literal_index());
4057 return ast_context()->ReturnInstruction(instr, expr->id()); 4021 return ast_context()->ReturnInstruction(instr, expr->id());
4058 } 4022 }
4059 4023
4060 4024
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
4217 *pointer_size += boilerplate->map()->instance_size(); 4181 *pointer_size += boilerplate->map()->instance_size();
4218 return true; 4182 return true;
4219 } 4183 }
4220 4184
4221 4185
4222 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 4186 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
4223 ASSERT(!HasStackOverflow()); 4187 ASSERT(!HasStackOverflow());
4224 ASSERT(current_block() != NULL); 4188 ASSERT(current_block() != NULL);
4225 ASSERT(current_block()->HasPredecessor()); 4189 ASSERT(current_block()->HasPredecessor());
4226 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 4190 Handle<JSFunction> closure = function_state()->compilation_info()->closure();
4227 HValue* context = environment()->LookupContext(); 4191 HValue* context = environment()->context();
4228 HInstruction* literal; 4192 HInstruction* literal;
4229 4193
4230 // Check whether to use fast or slow deep-copying for boilerplate. 4194 // Check whether to use fast or slow deep-copying for boilerplate.
4231 int data_size = 0; 4195 int data_size = 0;
4232 int pointer_size = 0; 4196 int pointer_size = 0;
4233 int max_properties = kMaxFastLiteralProperties; 4197 int max_properties = kMaxFastLiteralProperties;
4234 Handle<Object> original_boilerplate(closure->literals()->get( 4198 Handle<Object> original_boilerplate(closure->literals()->get(
4235 expr->literal_index()), isolate()); 4199 expr->literal_index()), isolate());
4236 if (original_boilerplate->IsJSObject() && 4200 if (original_boilerplate->IsJSObject() &&
4237 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), 4201 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate),
(...skipping 24 matching lines...) Expand all
4262 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; 4226 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
4263 4227
4264 Add<HPushArgument>(Add<HConstant>(closure_literals)); 4228 Add<HPushArgument>(Add<HConstant>(closure_literals));
4265 Add<HPushArgument>(Add<HConstant>(literal_index)); 4229 Add<HPushArgument>(Add<HConstant>(literal_index));
4266 Add<HPushArgument>(Add<HConstant>(constant_properties)); 4230 Add<HPushArgument>(Add<HConstant>(constant_properties));
4267 Add<HPushArgument>(Add<HConstant>(flags)); 4231 Add<HPushArgument>(Add<HConstant>(flags));
4268 4232
4269 Runtime::FunctionId function_id = 4233 Runtime::FunctionId function_id =
4270 (expr->depth() > 1 || expr->may_store_doubles()) 4234 (expr->depth() > 1 || expr->may_store_doubles())
4271 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; 4235 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow;
4272 literal = Add<HCallRuntime>(context, 4236 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
4273 isolate()->factory()->empty_string(),
4274 Runtime::FunctionForId(function_id), 4237 Runtime::FunctionForId(function_id),
4275 4); 4238 4);
4276 } 4239 }
4277 4240
4278 // The object is expected in the bailout environment during computation 4241 // The object is expected in the bailout environment during computation
4279 // of the property values and is the value of the entire expression. 4242 // of the property values and is the value of the entire expression.
4280 Push(literal); 4243 Push(literal);
4281 4244
4282 expr->CalculateEmitStore(zone()); 4245 expr->CalculateEmitStore(zone());
4283 4246
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4320 } 4283 }
4321 } else { 4284 } else {
4322 CHECK_ALIVE(VisitForEffect(value)); 4285 CHECK_ALIVE(VisitForEffect(value));
4323 } 4286 }
4324 break; 4287 break;
4325 } 4288 }
4326 // Fall through. 4289 // Fall through.
4327 case ObjectLiteral::Property::PROTOTYPE: 4290 case ObjectLiteral::Property::PROTOTYPE:
4328 case ObjectLiteral::Property::SETTER: 4291 case ObjectLiteral::Property::SETTER:
4329 case ObjectLiteral::Property::GETTER: 4292 case ObjectLiteral::Property::GETTER:
4330 return Bailout("Object literal with complex property"); 4293 return Bailout(kObjectLiteralWithComplexProperty);
4331 default: UNREACHABLE(); 4294 default: UNREACHABLE();
4332 } 4295 }
4333 } 4296 }
4334 4297
4335 if (expr->has_function()) { 4298 if (expr->has_function()) {
4336 // Return the result of the transformation to fast properties 4299 // Return the result of the transformation to fast properties
4337 // instead of the original since this operation changes the map 4300 // instead of the original since this operation changes the map
4338 // of the object. This makes sure that the original object won't 4301 // of the object. This makes sure that the original object won't
4339 // be used by other optimized code before it is transformed 4302 // be used by other optimized code before it is transformed
4340 // (e.g. because of code motion). 4303 // (e.g. because of code motion).
4341 HToFastProperties* result = Add<HToFastProperties>(Pop()); 4304 HToFastProperties* result = Add<HToFastProperties>(Pop());
4342 return ast_context()->ReturnValue(result); 4305 return ast_context()->ReturnValue(result);
4343 } else { 4306 } else {
4344 return ast_context()->ReturnValue(Pop()); 4307 return ast_context()->ReturnValue(Pop());
4345 } 4308 }
4346 } 4309 }
4347 4310
4348 4311
4349 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 4312 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
4350 ASSERT(!HasStackOverflow()); 4313 ASSERT(!HasStackOverflow());
4351 ASSERT(current_block() != NULL); 4314 ASSERT(current_block() != NULL);
4352 ASSERT(current_block()->HasPredecessor()); 4315 ASSERT(current_block()->HasPredecessor());
4353 ZoneList<Expression*>* subexprs = expr->values(); 4316 ZoneList<Expression*>* subexprs = expr->values();
4354 int length = subexprs->length(); 4317 int length = subexprs->length();
4355 HValue* context = environment()->LookupContext(); 4318 HValue* context = environment()->context();
4356 HInstruction* literal; 4319 HInstruction* literal;
4357 4320
4358 Handle<AllocationSite> site; 4321 Handle<AllocationSite> site;
4359 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); 4322 Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
4360 bool uninitialized = false; 4323 bool uninitialized = false;
4361 Handle<Object> literals_cell(literals->get(expr->literal_index()), 4324 Handle<Object> literals_cell(literals->get(expr->literal_index()),
4362 isolate()); 4325 isolate());
4363 Handle<Object> raw_boilerplate; 4326 Handle<Object> raw_boilerplate;
4364 if (literals_cell->IsUndefined()) { 4327 if (literals_cell->IsUndefined()) {
4365 uninitialized = true; 4328 uninitialized = true;
4366 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( 4329 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
4367 isolate(), literals, expr->constant_elements()); 4330 isolate(), literals, expr->constant_elements());
4368 if (raw_boilerplate.is_null()) { 4331 if (raw_boilerplate.is_null()) {
4369 return Bailout("array boilerplate creation failed"); 4332 return Bailout(kArrayBoilerplateCreationFailed);
4370 } 4333 }
4371 4334
4372 site = isolate()->factory()->NewAllocationSite(); 4335 site = isolate()->factory()->NewAllocationSite();
4373 site->set_transition_info(*raw_boilerplate); 4336 site->set_transition_info(*raw_boilerplate);
4374 literals->set(expr->literal_index(), *site); 4337 literals->set(expr->literal_index(), *site);
4375 4338
4376 if (JSObject::cast(*raw_boilerplate)->elements()->map() == 4339 if (JSObject::cast(*raw_boilerplate)->elements()->map() ==
4377 isolate()->heap()->fixed_cow_array_map()) { 4340 isolate()->heap()->fixed_cow_array_map()) {
4378 isolate()->counters()->cow_arrays_created_runtime()->Increment(); 4341 isolate()->counters()->cow_arrays_created_runtime()->Increment();
4379 } 4342 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4424 // pass an empty fixed array to the runtime function instead. 4387 // pass an empty fixed array to the runtime function instead.
4425 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); 4388 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
4426 int literal_index = expr->literal_index(); 4389 int literal_index = expr->literal_index();
4427 4390
4428 Add<HPushArgument>(Add<HConstant>(literals)); 4391 Add<HPushArgument>(Add<HConstant>(literals));
4429 Add<HPushArgument>(Add<HConstant>(literal_index)); 4392 Add<HPushArgument>(Add<HConstant>(literal_index));
4430 Add<HPushArgument>(Add<HConstant>(constants)); 4393 Add<HPushArgument>(Add<HConstant>(constants));
4431 4394
4432 Runtime::FunctionId function_id = (expr->depth() > 1) 4395 Runtime::FunctionId function_id = (expr->depth() > 1)
4433 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; 4396 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow;
4434 literal = Add<HCallRuntime>(context, 4397 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
4435 isolate()->factory()->empty_string(),
4436 Runtime::FunctionForId(function_id), 4398 Runtime::FunctionForId(function_id),
4437 3); 4399 3);
4438 4400
4439 // De-opt if elements kind changed from boilerplate_elements_kind. 4401 // De-opt if elements kind changed from boilerplate_elements_kind.
4440 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), 4402 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(),
4441 isolate()); 4403 isolate());
4442 AddInstruction(HCheckMaps::New(literal, map, zone(), top_info())); 4404 Add<HCheckMaps>(literal, map, top_info());
4443 } 4405 }
4444 4406
4445 // The array is expected in the bailout environment during computation 4407 // The array is expected in the bailout environment during computation
4446 // of the property values and is the value of the entire expression. 4408 // of the property values and is the value of the entire expression.
4447 Push(literal); 4409 Push(literal);
4448 // The literal index is on the stack, too. 4410 // The literal index is on the stack, too.
4449 Push(Add<HConstant>(expr->literal_index())); 4411 Push(Add<HConstant>(expr->literal_index()));
4450 4412
4451 HInstruction* elements = NULL; 4413 HInstruction* elements = NULL;
4452 4414
4453 for (int i = 0; i < length; i++) { 4415 for (int i = 0; i < length; i++) {
4454 Expression* subexpr = subexprs->at(i); 4416 Expression* subexpr = subexprs->at(i);
4455 // If the subexpression is a literal or a simple materialized literal it 4417 // If the subexpression is a literal or a simple materialized literal it
4456 // is already set in the cloned array. 4418 // is already set in the cloned array.
4457 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 4419 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
4458 4420
4459 CHECK_ALIVE(VisitForValue(subexpr)); 4421 CHECK_ALIVE(VisitForValue(subexpr));
4460 HValue* value = Pop(); 4422 HValue* value = Pop();
4461 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); 4423 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
4462 4424
4463 elements = AddLoadElements(literal); 4425 elements = AddLoadElements(literal);
4464 4426
4465 HValue* key = Add<HConstant>(i); 4427 HValue* key = Add<HConstant>(i);
4466 4428
4467 switch (boilerplate_elements_kind) { 4429 switch (boilerplate_elements_kind) {
4468 case FAST_SMI_ELEMENTS: 4430 case FAST_SMI_ELEMENTS:
4469 case FAST_HOLEY_SMI_ELEMENTS: 4431 case FAST_HOLEY_SMI_ELEMENTS:
4470 case FAST_ELEMENTS: 4432 case FAST_ELEMENTS:
4471 case FAST_HOLEY_ELEMENTS: 4433 case FAST_HOLEY_ELEMENTS:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
4509 // 2nd chance: A store into a non-existent field can still be inlined if we 4471 // 2nd chance: A store into a non-existent field can still be inlined if we
4510 // have a matching transition and some room left in the object. 4472 // have a matching transition and some room left in the object.
4511 type->LookupTransition(NULL, *name, lookup); 4473 type->LookupTransition(NULL, *name, lookup);
4512 return lookup->IsTransitionToField(*type) && 4474 return lookup->IsTransitionToField(*type) &&
4513 (type->unused_property_fields() > 0); 4475 (type->unused_property_fields() > 0);
4514 } 4476 }
4515 4477
4516 4478
4517 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { 4479 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) {
4518 BuildCheckHeapObject(object); 4480 BuildCheckHeapObject(object);
4519 AddInstruction(HCheckMaps::New(object, map, zone(), top_info())); 4481 Add<HCheckMaps>(object, map, top_info());
4520 } 4482 }
4521 4483
4522 4484
4523 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object,
4524 Handle<Map> map) {
4525 BuildCheckHeapObject(object);
4526 AddInstruction(HCheckMaps::NewWithTransitions(
4527 object, map, zone(), top_info()));
4528 }
4529
4530
4531 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( 4485 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
4532 HValue* object, 4486 HValue* object,
4533 Handle<String> name, 4487 Handle<String> name,
4534 HValue* value, 4488 HValue* value,
4535 Handle<Map> map, 4489 Handle<Map> map,
4536 LookupResult* lookup) { 4490 LookupResult* lookup) {
4537 ASSERT(lookup->IsFound()); 4491 ASSERT(lookup->IsFound());
4538 // If the property does not exist yet, we have to check that it wasn't made 4492 // If the property does not exist yet, we have to check that it wasn't made
4539 // readonly or turned into a setter by some meanwhile modifications on the 4493 // readonly or turned into a setter by some meanwhile modifications on the
4540 // prototype chain. 4494 // prototype chain.
4541 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { 4495 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) {
4542 Object* proto = map->prototype(); 4496 Object* proto = map->prototype();
4543 // First check that the prototype chain isn't affected already. 4497 // First check that the prototype chain isn't affected already.
4544 LookupResult proto_result(isolate()); 4498 LookupResult proto_result(isolate());
4545 proto->Lookup(*name, &proto_result); 4499 proto->Lookup(*name, &proto_result);
4546 if (proto_result.IsProperty()) { 4500 if (proto_result.IsProperty()) {
4547 // If the inherited property could induce readonly-ness, bail out. 4501 // If the inherited property could induce readonly-ness, bail out.
4548 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) { 4502 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) {
4549 Bailout("improper object on prototype chain for store"); 4503 Bailout(kImproperObjectOnPrototypeChainForStore);
4550 return NULL; 4504 return NULL;
4551 } 4505 }
4552 // We only need to check up to the preexisting property. 4506 // We only need to check up to the preexisting property.
4553 proto = proto_result.holder(); 4507 proto = proto_result.holder();
4554 } else { 4508 } else {
4555 // Otherwise, find the top prototype. 4509 // Otherwise, find the top prototype.
4556 while (proto->GetPrototype(isolate())->IsJSObject()) { 4510 while (proto->GetPrototype(isolate())->IsJSObject()) {
4557 proto = proto->GetPrototype(isolate()); 4511 proto = proto->GetPrototype(isolate());
4558 } 4512 }
4559 ASSERT(proto->GetPrototype(isolate())->IsNull()); 4513 ASSERT(proto->GetPrototype(isolate())->IsNull());
4560 } 4514 }
4561 ASSERT(proto->IsJSObject()); 4515 ASSERT(proto->IsJSObject());
4562 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), 4516 Add<HCheckPrototypeMaps>(
4563 Handle<JSObject>(JSObject::cast(proto)), 4517 Handle<JSObject>(JSObject::cast(map->prototype())),
4564 zone(), top_info()); 4518 Handle<JSObject>(JSObject::cast(proto)), top_info());
4565 } 4519 }
4566 4520
4567 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); 4521 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
4568 bool transition_to_field = lookup->IsTransitionToField(*map); 4522 bool transition_to_field = lookup->IsTransitionToField(*map);
4569 4523
4570 HStoreNamedField *instr; 4524 HStoreNamedField *instr;
4571 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { 4525 if (FLAG_track_double_fields && field_access.representation().IsDouble()) {
4572 HObjectAccess heap_number_access = 4526 HObjectAccess heap_number_access =
4573 field_access.WithRepresentation(Representation::Tagged()); 4527 field_access.WithRepresentation(Representation::Tagged());
4574 if (transition_to_field) { 4528 if (transition_to_field) {
4575 // The store requires a mutable HeapNumber to be allocated. 4529 // The store requires a mutable HeapNumber to be allocated.
4576 NoObservableSideEffectsScope no_side_effects(this); 4530 NoObservableSideEffectsScope no_side_effects(this);
4577 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); 4531 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
4578 HInstruction* heap_number = Add<HAllocate>( 4532 HInstruction* heap_number = Add<HAllocate>(heap_number_size,
4579 environment()->LookupContext(), heap_number_size, 4533 HType::HeapNumber(), isolate()->heap()->GetPretenureMode(),
4580 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); 4534 HEAP_NUMBER_TYPE);
4581 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); 4535 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map());
4582 AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value); 4536 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
4583 instr = new(zone()) HStoreNamedField( 4537 value);
4584 object, heap_number_access, heap_number); 4538 instr = New<HStoreNamedField>(object, heap_number_access,
4539 heap_number);
4585 } else { 4540 } else {
4586 // Already holds a HeapNumber; load the box and write its value field. 4541 // Already holds a HeapNumber; load the box and write its value field.
4587 HInstruction* heap_number = AddLoad(object, heap_number_access); 4542 HInstruction* heap_number = Add<HLoadNamedField>(object,
4543 heap_number_access);
4588 heap_number->set_type(HType::HeapNumber()); 4544 heap_number->set_type(HType::HeapNumber());
4589 instr = new(zone()) HStoreNamedField(heap_number, 4545 instr = New<HStoreNamedField>(heap_number,
4590 HObjectAccess::ForHeapNumberValue(), value); 4546 HObjectAccess::ForHeapNumberValue(),
4547 value);
4591 } 4548 }
4592 } else { 4549 } else {
4593 // This is a normal store. 4550 // This is a normal store.
4594 instr = new(zone()) HStoreNamedField(object, field_access, value); 4551 instr = New<HStoreNamedField>(object, field_access, value);
4595 } 4552 }
4596 4553
4597 if (transition_to_field) { 4554 if (transition_to_field) {
4598 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); 4555 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
4599 instr->SetTransition(transition, top_info()); 4556 instr->SetTransition(transition, top_info());
4600 // TODO(fschneider): Record the new map type of the object in the IR to 4557 // TODO(fschneider): Record the new map type of the object in the IR to
4601 // enable elimination of redundant checks after the transition store. 4558 // enable elimination of redundant checks after the transition store.
4602 instr->SetGVNFlag(kChangesMaps); 4559 instr->SetGVNFlag(kChangesMaps);
4603 } 4560 }
4604 return instr; 4561 return instr;
4605 } 4562 }
4606 4563
4607 4564
4608 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( 4565 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
4609 HValue* object, 4566 HValue* object,
4610 Handle<String> name, 4567 Handle<String> name,
4611 HValue* value) { 4568 HValue* value) {
4612 HValue* context = environment()->LookupContext(); 4569 HValue* context = environment()->context();
4613 return new(zone()) HStoreNamedGeneric( 4570 return new(zone()) HStoreNamedGeneric(
4614 context, 4571 context,
4615 object, 4572 object,
4616 name, 4573 name,
4617 value, 4574 value,
4618 function_strict_mode_flag()); 4575 function_strict_mode_flag());
4619 } 4576 }
4620 4577
4621 4578
4622 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( 4579 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
4623 HValue* object, 4580 HValue* object,
4624 Handle<String> name, 4581 Handle<String> name,
4625 HValue* value, 4582 HValue* value,
4626 Handle<Map> map) { 4583 Handle<Map> map) {
4627 // Handle a store to a known field. 4584 // Handle a store to a known field.
4628 LookupResult lookup(isolate()); 4585 LookupResult lookup(isolate());
4629 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4586 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4630 AddCheckMapsWithTransitions(object, map); 4587 AddCheckMap(object, map);
4631 return BuildStoreNamedField(object, name, value, map, &lookup); 4588 return BuildStoreNamedField(object, name, value, map, &lookup);
4632 } 4589 }
4633 4590
4634 // No luck, do a generic store. 4591 // No luck, do a generic store.
4635 return BuildStoreNamedGeneric(object, name, value); 4592 return BuildStoreNamedGeneric(object, name, value);
4636 } 4593 }
4637 4594
4638 4595
4639 static bool CanLoadPropertyFromPrototype(Handle<Map> map, 4596 static bool CanLoadPropertyFromPrototype(Handle<Map> map,
4640 Handle<Name> name, 4597 Handle<Name> name,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4679 // In-objectness did not match. 4636 // In-objectness did not match.
4680 break; 4637 break;
4681 } 4638 }
4682 access = access.WithRepresentation( 4639 access = access.WithRepresentation(
4683 access.representation().generalize(new_access.representation())); 4640 access.representation().generalize(new_access.representation()));
4684 } 4641 }
4685 4642
4686 if (count == types->length()) { 4643 if (count == types->length()) {
4687 // Everything matched; can use monomorphic load. 4644 // Everything matched; can use monomorphic load.
4688 BuildCheckHeapObject(object); 4645 BuildCheckHeapObject(object);
4689 AddInstruction(HCheckMaps::New(object, types, zone())); 4646 Add<HCheckMaps>(object, types);
4690 return BuildLoadNamedField(object, access); 4647 return BuildLoadNamedField(object, access);
4691 } 4648 }
4692 4649
4693 if (count != 0) return NULL; 4650 if (count != 0) return NULL;
4694 4651
4695 // Second chance: the property is on the prototype and all maps have the 4652 // Second chance: the property is on the prototype and all maps have the
4696 // same prototype. 4653 // same prototype.
4697 Handle<Map> map(types->at(0)); 4654 Handle<Map> map(types->at(0));
4698 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; 4655 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL;
4699 4656
4700 Handle<Object> prototype(map->prototype(), isolate()); 4657 Handle<Object> prototype(map->prototype(), isolate());
4701 for (count = 1; count < types->length(); ++count) { 4658 for (count = 1; count < types->length(); ++count) {
4702 Handle<Map> test_map(types->at(count)); 4659 Handle<Map> test_map(types->at(count));
4703 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; 4660 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL;
4704 if (test_map->prototype() != *prototype) return NULL; 4661 if (test_map->prototype() != *prototype) return NULL;
4705 } 4662 }
4706 4663
4707 LookupInPrototypes(map, name, &lookup); 4664 LookupInPrototypes(map, name, &lookup);
4708 if (!lookup.IsField()) return NULL; 4665 if (!lookup.IsField()) return NULL;
4709 4666
4710 BuildCheckHeapObject(object); 4667 BuildCheckHeapObject(object);
4711 AddInstruction(HCheckMaps::New(object, types, zone())); 4668 Add<HCheckMaps>(object, types);
4712 4669
4713 Handle<JSObject> holder(lookup.holder()); 4670 Handle<JSObject> holder(lookup.holder());
4714 Handle<Map> holder_map(holder->map()); 4671 Handle<Map> holder_map(holder->map());
4715 AddInstruction(new(zone()) HCheckPrototypeMaps( 4672 Add<HCheckPrototypeMaps>(
4716 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); 4673 Handle<JSObject>::cast(prototype), holder, top_info());
4717 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); 4674 HValue* holder_value = Add<HConstant>(holder);
4718 return BuildLoadNamedField(holder_value, 4675 return BuildLoadNamedField(holder_value,
4719 HObjectAccess::ForField(holder_map, &lookup, name)); 4676 HObjectAccess::ForField(holder_map, &lookup, name));
4720 } 4677 }
4721 4678
4722 4679
4723 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4680 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4724 Property* expr, 4681 Property* expr,
4725 HValue* object, 4682 HValue* object,
4726 SmallMapList* types, 4683 SmallMapList* types,
4727 Handle<String> name) { 4684 Handle<String> name) {
4728 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( 4685 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(
4729 expr, object, types, name); 4686 expr, object, types, name);
4730 if (instr == NULL) { 4687 if (instr == NULL) {
4731 // Something did not match; must use a polymorphic load. 4688 // Something did not match; must use a polymorphic load.
4732 BuildCheckHeapObject(object); 4689 BuildCheckHeapObject(object);
4733 HValue* context = environment()->LookupContext(); 4690 HValue* context = environment()->context();
4734 instr = new(zone()) HLoadNamedFieldPolymorphic( 4691 instr = new(zone()) HLoadNamedFieldPolymorphic(
4735 context, object, types, name, zone()); 4692 context, object, types, name, zone());
4736 } 4693 }
4737 4694
4738 instr->set_position(expr->position()); 4695 instr->set_position(expr->position());
4739 return ast_context()->ReturnInstruction(instr, expr->id()); 4696 return ast_context()->ReturnInstruction(instr, expr->id());
4740 } 4697 }
4741 4698
4742 4699
4743 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( 4700 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4780 } else if (access.IsInobject() != new_access.IsInobject()) { 4737 } else if (access.IsInobject() != new_access.IsInobject()) {
4781 // In-objectness did not match. 4738 // In-objectness did not match.
4782 break; 4739 break;
4783 } 4740 }
4784 } 4741 }
4785 4742
4786 if (count != types->length()) return false; 4743 if (count != types->length()) return false;
4787 4744
4788 // Everything matched; can use monomorphic store. 4745 // Everything matched; can use monomorphic store.
4789 BuildCheckHeapObject(object); 4746 BuildCheckHeapObject(object);
4790 AddInstruction(HCheckMaps::New(object, types, zone())); 4747 Add<HCheckMaps>(object, types);
4791 HInstruction* store; 4748 HInstruction* store;
4792 CHECK_ALIVE_OR_RETURN( 4749 CHECK_ALIVE_OR_RETURN(
4793 store = BuildStoreNamedField( 4750 store = BuildStoreNamedField(
4794 object, name, store_value, types->at(count - 1), &lookup), 4751 object, name, store_value, types->at(count - 1), &lookup),
4795 true); 4752 true);
4796 if (!ast_context()->IsEffect()) Push(result_value); 4753 if (!ast_context()->IsEffect()) Push(result_value);
4797 store->set_position(position); 4754 store->set_position(position);
4798 AddInstruction(store); 4755 AddInstruction(store);
4799 Add<HSimulate>(assignment_id); 4756 Add<HSimulate>(assignment_id);
4800 if (!ast_context()->IsEffect()) Drop(1); 4757 if (!ast_context()->IsEffect()) Drop(1);
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
4952 Add<HDeoptimize>(Deoptimizer::EAGER); 4909 Add<HDeoptimize>(Deoptimizer::EAGER);
4953 builder.End(); 4910 builder.End();
4954 } 4911 }
4955 HInstruction* instr = 4912 HInstruction* instr =
4956 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); 4913 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
4957 instr->set_position(position); 4914 instr->set_position(position);
4958 if (instr->HasObservableSideEffects()) { 4915 if (instr->HasObservableSideEffects()) {
4959 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 4916 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4960 } 4917 }
4961 } else { 4918 } else {
4962 HValue* context = environment()->LookupContext(); 4919 HGlobalObject* global_object = Add<HGlobalObject>();
4963 HGlobalObject* global_object = Add<HGlobalObject>(context);
4964 HStoreGlobalGeneric* instr = 4920 HStoreGlobalGeneric* instr =
4965 Add<HStoreGlobalGeneric>(context, global_object, var->name(), 4921 Add<HStoreGlobalGeneric>(global_object, var->name(),
4966 value, function_strict_mode_flag()); 4922 value, function_strict_mode_flag());
4967 instr->set_position(position); 4923 instr->set_position(position);
4968 ASSERT(instr->HasObservableSideEffects()); 4924 ASSERT(instr->HasObservableSideEffects());
4969 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 4925 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4970 } 4926 }
4971 } 4927 }
4972 4928
4973 4929
4974 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, 4930 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
4975 BailoutId id, 4931 BailoutId id,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
5041 Property* prop = target->AsProperty(); 4997 Property* prop = target->AsProperty();
5042 ASSERT(proxy == NULL || prop == NULL); 4998 ASSERT(proxy == NULL || prop == NULL);
5043 4999
5044 // We have a second position recorded in the FullCodeGenerator to have 5000 // We have a second position recorded in the FullCodeGenerator to have
5045 // type feedback for the binary operation. 5001 // type feedback for the binary operation.
5046 BinaryOperation* operation = expr->binary_operation(); 5002 BinaryOperation* operation = expr->binary_operation();
5047 5003
5048 if (proxy != NULL) { 5004 if (proxy != NULL) {
5049 Variable* var = proxy->var(); 5005 Variable* var = proxy->var();
5050 if (var->mode() == LET) { 5006 if (var->mode() == LET) {
5051 return Bailout("unsupported let compound assignment"); 5007 return Bailout(kUnsupportedLetCompoundAssignment);
5052 } 5008 }
5053 5009
5054 CHECK_ALIVE(VisitForValue(operation)); 5010 CHECK_ALIVE(VisitForValue(operation));
5055 5011
5056 switch (var->location()) { 5012 switch (var->location()) {
5057 case Variable::UNALLOCATED: 5013 case Variable::UNALLOCATED:
5058 HandleGlobalVariableAssignment(var, 5014 HandleGlobalVariableAssignment(var,
5059 Top(), 5015 Top(),
5060 expr->position(), 5016 expr->position(),
5061 expr->AssignmentId()); 5017 expr->AssignmentId());
5062 break; 5018 break;
5063 5019
5064 case Variable::PARAMETER: 5020 case Variable::PARAMETER:
5065 case Variable::LOCAL: 5021 case Variable::LOCAL:
5066 if (var->mode() == CONST) { 5022 if (var->mode() == CONST) {
5067 return Bailout("unsupported const compound assignment"); 5023 return Bailout(kUnsupportedConstCompoundAssignment);
5068 } 5024 }
5069 BindIfLive(var, Top()); 5025 BindIfLive(var, Top());
5070 break; 5026 break;
5071 5027
5072 case Variable::CONTEXT: { 5028 case Variable::CONTEXT: {
5073 // Bail out if we try to mutate a parameter value in a function 5029 // Bail out if we try to mutate a parameter value in a function
5074 // using the arguments object. We do not (yet) correctly handle the 5030 // using the arguments object. We do not (yet) correctly handle the
5075 // arguments property of the function. 5031 // arguments property of the function.
5076 if (current_info()->scope()->arguments() != NULL) { 5032 if (current_info()->scope()->arguments() != NULL) {
5077 // Parameters will be allocated to context slots. We have no 5033 // Parameters will be allocated to context slots. We have no
5078 // direct way to detect that the variable is a parameter so we do 5034 // direct way to detect that the variable is a parameter so we do
5079 // a linear search of the parameter variables. 5035 // a linear search of the parameter variables.
5080 int count = current_info()->scope()->num_parameters(); 5036 int count = current_info()->scope()->num_parameters();
5081 for (int i = 0; i < count; ++i) { 5037 for (int i = 0; i < count; ++i) {
5082 if (var == current_info()->scope()->parameter(i)) { 5038 if (var == current_info()->scope()->parameter(i)) {
5083 Bailout( 5039 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
5084 "assignment to parameter, function uses arguments object");
5085 } 5040 }
5086 } 5041 }
5087 } 5042 }
5088 5043
5089 HStoreContextSlot::Mode mode; 5044 HStoreContextSlot::Mode mode;
5090 5045
5091 switch (var->mode()) { 5046 switch (var->mode()) {
5092 case LET: 5047 case LET:
5093 mode = HStoreContextSlot::kCheckDeoptimize; 5048 mode = HStoreContextSlot::kCheckDeoptimize;
5094 break; 5049 break;
5095 case CONST: 5050 case CONST:
5096 return ast_context()->ReturnValue(Pop()); 5051 return ast_context()->ReturnValue(Pop());
5097 case CONST_HARMONY: 5052 case CONST_HARMONY:
5098 // This case is checked statically so no need to 5053 // This case is checked statically so no need to
5099 // perform checks here 5054 // perform checks here
5100 UNREACHABLE(); 5055 UNREACHABLE();
5101 default: 5056 default:
5102 mode = HStoreContextSlot::kNoCheck; 5057 mode = HStoreContextSlot::kNoCheck;
5103 } 5058 }
5104 5059
5105 HValue* context = BuildContextChainWalk(var); 5060 HValue* context = BuildContextChainWalk(var);
5106 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), 5061 HStoreContextSlot* instr = Add<HStoreContextSlot>(
5107 mode, Top()); 5062 context, var->index(), mode, Top());
5108 if (instr->HasObservableSideEffects()) { 5063 if (instr->HasObservableSideEffects()) {
5109 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); 5064 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
5110 } 5065 }
5111 break; 5066 break;
5112 } 5067 }
5113 5068
5114 case Variable::LOOKUP: 5069 case Variable::LOOKUP:
5115 return Bailout("compound assignment to lookup slot"); 5070 return Bailout(kCompoundAssignmentToLookupSlot);
5116 } 5071 }
5117 return ast_context()->ReturnValue(Pop()); 5072 return ast_context()->ReturnValue(Pop());
5118 5073
5119 } else if (prop != NULL) { 5074 } else if (prop != NULL) {
5120 if (prop->key()->IsPropertyName()) { 5075 if (prop->key()->IsPropertyName()) {
5121 // Named property. 5076 // Named property.
5122 CHECK_ALIVE(VisitForValue(prop->obj())); 5077 CHECK_ALIVE(VisitForValue(prop->obj()));
5123 HValue* object = Top(); 5078 HValue* object = Top();
5124 5079
5125 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 5080 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
5194 5149
5195 // Drop the simulated receiver, key, and value. Return the value. 5150 // Drop the simulated receiver, key, and value. Return the value.
5196 Drop(3); 5151 Drop(3);
5197 Push(instr); 5152 Push(instr);
5198 ASSERT(has_side_effects); // Stores always have side effects. 5153 ASSERT(has_side_effects); // Stores always have side effects.
5199 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); 5154 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
5200 return ast_context()->ReturnValue(Pop()); 5155 return ast_context()->ReturnValue(Pop());
5201 } 5156 }
5202 5157
5203 } else { 5158 } else {
5204 return Bailout("invalid lhs in compound assignment"); 5159 return Bailout(kInvalidLhsInCompoundAssignment);
5205 } 5160 }
5206 } 5161 }
5207 5162
5208 5163
5209 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { 5164 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
5210 ASSERT(!HasStackOverflow()); 5165 ASSERT(!HasStackOverflow());
5211 ASSERT(current_block() != NULL); 5166 ASSERT(current_block() != NULL);
5212 ASSERT(current_block()->HasPredecessor()); 5167 ASSERT(current_block()->HasPredecessor());
5213 VariableProxy* proxy = expr->target()->AsVariableProxy(); 5168 VariableProxy* proxy = expr->target()->AsVariableProxy();
5214 Property* prop = expr->target()->AsProperty(); 5169 Property* prop = expr->target()->AsProperty();
(...skipping 16 matching lines...) Expand all
5231 } 5186 }
5232 5187
5233 if (var->IsStackAllocated()) { 5188 if (var->IsStackAllocated()) {
5234 // We insert a use of the old value to detect unsupported uses of const 5189 // We insert a use of the old value to detect unsupported uses of const
5235 // variables (e.g. initialization inside a loop). 5190 // variables (e.g. initialization inside a loop).
5236 HValue* old_value = environment()->Lookup(var); 5191 HValue* old_value = environment()->Lookup(var);
5237 Add<HUseConst>(old_value); 5192 Add<HUseConst>(old_value);
5238 } 5193 }
5239 } else if (var->mode() == CONST_HARMONY) { 5194 } else if (var->mode() == CONST_HARMONY) {
5240 if (expr->op() != Token::INIT_CONST_HARMONY) { 5195 if (expr->op() != Token::INIT_CONST_HARMONY) {
5241 return Bailout("non-initializer assignment to const"); 5196 return Bailout(kNonInitializerAssignmentToConst);
5242 } 5197 }
5243 } 5198 }
5244 5199
5245 if (proxy->IsArguments()) return Bailout("assignment to arguments"); 5200 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
5246 5201
5247 // Handle the assignment. 5202 // Handle the assignment.
5248 switch (var->location()) { 5203 switch (var->location()) {
5249 case Variable::UNALLOCATED: 5204 case Variable::UNALLOCATED:
5250 CHECK_ALIVE(VisitForValue(expr->value())); 5205 CHECK_ALIVE(VisitForValue(expr->value()));
5251 HandleGlobalVariableAssignment(var, 5206 HandleGlobalVariableAssignment(var,
5252 Top(), 5207 Top(),
5253 expr->position(), 5208 expr->position(),
5254 expr->AssignmentId()); 5209 expr->AssignmentId());
5255 return ast_context()->ReturnValue(Pop()); 5210 return ast_context()->ReturnValue(Pop());
5256 5211
5257 case Variable::PARAMETER: 5212 case Variable::PARAMETER:
5258 case Variable::LOCAL: { 5213 case Variable::LOCAL: {
5259 // Perform an initialization check for let declared variables 5214 // Perform an initialization check for let declared variables
5260 // or parameters. 5215 // or parameters.
5261 if (var->mode() == LET && expr->op() == Token::ASSIGN) { 5216 if (var->mode() == LET && expr->op() == Token::ASSIGN) {
5262 HValue* env_value = environment()->Lookup(var); 5217 HValue* env_value = environment()->Lookup(var);
5263 if (env_value == graph()->GetConstantHole()) { 5218 if (env_value == graph()->GetConstantHole()) {
5264 return Bailout("assignment to let variable before initialization"); 5219 return Bailout(kAssignmentToLetVariableBeforeInitialization);
5265 } 5220 }
5266 } 5221 }
5267 // We do not allow the arguments object to occur in a context where it 5222 // We do not allow the arguments object to occur in a context where it
5268 // may escape, but assignments to stack-allocated locals are 5223 // may escape, but assignments to stack-allocated locals are
5269 // permitted. 5224 // permitted.
5270 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); 5225 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
5271 HValue* value = Pop(); 5226 HValue* value = Pop();
5272 BindIfLive(var, value); 5227 BindIfLive(var, value);
5273 return ast_context()->ReturnValue(value); 5228 return ast_context()->ReturnValue(value);
5274 } 5229 }
5275 5230
5276 case Variable::CONTEXT: { 5231 case Variable::CONTEXT: {
5277 // Bail out if we try to mutate a parameter value in a function using 5232 // Bail out if we try to mutate a parameter value in a function using
5278 // the arguments object. We do not (yet) correctly handle the 5233 // the arguments object. We do not (yet) correctly handle the
5279 // arguments property of the function. 5234 // arguments property of the function.
5280 if (current_info()->scope()->arguments() != NULL) { 5235 if (current_info()->scope()->arguments() != NULL) {
5281 // Parameters will rewrite to context slots. We have no direct way 5236 // Parameters will rewrite to context slots. We have no direct way
5282 // to detect that the variable is a parameter. 5237 // to detect that the variable is a parameter.
5283 int count = current_info()->scope()->num_parameters(); 5238 int count = current_info()->scope()->num_parameters();
5284 for (int i = 0; i < count; ++i) { 5239 for (int i = 0; i < count; ++i) {
5285 if (var == current_info()->scope()->parameter(i)) { 5240 if (var == current_info()->scope()->parameter(i)) {
5286 return Bailout("assignment to parameter in arguments object"); 5241 return Bailout(kAssignmentToParameterInArgumentsObject);
5287 } 5242 }
5288 } 5243 }
5289 } 5244 }
5290 5245
5291 CHECK_ALIVE(VisitForValue(expr->value())); 5246 CHECK_ALIVE(VisitForValue(expr->value()));
5292 HStoreContextSlot::Mode mode; 5247 HStoreContextSlot::Mode mode;
5293 if (expr->op() == Token::ASSIGN) { 5248 if (expr->op() == Token::ASSIGN) {
5294 switch (var->mode()) { 5249 switch (var->mode()) {
5295 case LET: 5250 case LET:
5296 mode = HStoreContextSlot::kCheckDeoptimize; 5251 mode = HStoreContextSlot::kCheckDeoptimize;
(...skipping 11 matching lines...) Expand all
5308 expr->op() == Token::INIT_LET || 5263 expr->op() == Token::INIT_LET ||
5309 expr->op() == Token::INIT_CONST_HARMONY) { 5264 expr->op() == Token::INIT_CONST_HARMONY) {
5310 mode = HStoreContextSlot::kNoCheck; 5265 mode = HStoreContextSlot::kNoCheck;
5311 } else { 5266 } else {
5312 ASSERT(expr->op() == Token::INIT_CONST); 5267 ASSERT(expr->op() == Token::INIT_CONST);
5313 5268
5314 mode = HStoreContextSlot::kCheckIgnoreAssignment; 5269 mode = HStoreContextSlot::kCheckIgnoreAssignment;
5315 } 5270 }
5316 5271
5317 HValue* context = BuildContextChainWalk(var); 5272 HValue* context = BuildContextChainWalk(var);
5318 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), 5273 HStoreContextSlot* instr = Add<HStoreContextSlot>(
5319 mode, Top()); 5274 context, var->index(), mode, Top());
5320 if (instr->HasObservableSideEffects()) { 5275 if (instr->HasObservableSideEffects()) {
5321 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); 5276 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
5322 } 5277 }
5323 return ast_context()->ReturnValue(Pop()); 5278 return ast_context()->ReturnValue(Pop());
5324 } 5279 }
5325 5280
5326 case Variable::LOOKUP: 5281 case Variable::LOOKUP:
5327 return Bailout("assignment to LOOKUP variable"); 5282 return Bailout(kAssignmentToLOOKUPVariable);
5328 } 5283 }
5329 } else { 5284 } else {
5330 return Bailout("invalid left-hand side in assignment"); 5285 return Bailout(kInvalidLeftHandSideInAssignment);
5331 } 5286 }
5332 } 5287 }
5333 5288
5334 5289
5335 void HOptimizedGraphBuilder::VisitYield(Yield* expr) { 5290 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
5336 // Generators are not optimized, so we should never get here. 5291 // Generators are not optimized, so we should never get here.
5337 UNREACHABLE(); 5292 UNREACHABLE();
5338 } 5293 }
5339 5294
5340 5295
5341 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { 5296 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
5342 ASSERT(!HasStackOverflow()); 5297 ASSERT(!HasStackOverflow());
5343 ASSERT(current_block() != NULL); 5298 ASSERT(current_block() != NULL);
5344 ASSERT(current_block()->HasPredecessor()); 5299 ASSERT(current_block()->HasPredecessor());
5345 // We don't optimize functions with invalid left-hand sides in 5300 // We don't optimize functions with invalid left-hand sides in
5346 // assignments, count operations, or for-in. Consequently throw can 5301 // assignments, count operations, or for-in. Consequently throw can
5347 // currently only occur in an effect context. 5302 // currently only occur in an effect context.
5348 ASSERT(ast_context()->IsEffect()); 5303 ASSERT(ast_context()->IsEffect());
5349 CHECK_ALIVE(VisitForValue(expr->exception())); 5304 CHECK_ALIVE(VisitForValue(expr->exception()));
5350 5305
5351 HValue* context = environment()->LookupContext();
5352 HValue* value = environment()->Pop(); 5306 HValue* value = environment()->Pop();
5353 HThrow* instr = Add<HThrow>(context, value); 5307 HThrow* instr = Add<HThrow>(value);
5354 instr->set_position(expr->position()); 5308 instr->set_position(expr->position());
5355 Add<HSimulate>(expr->id()); 5309 Add<HSimulate>(expr->id());
5356 current_block()->FinishExit(new(zone()) HAbnormalExit); 5310 current_block()->FinishExit(new(zone()) HAbnormalExit);
5357 set_current_block(NULL); 5311 set_current_block(NULL);
5358 } 5312 }
5359 5313
5360 5314
5361 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 5315 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
5362 HObjectAccess access) { 5316 HObjectAccess access,
5317 HValue* typecheck) {
5363 if (FLAG_track_double_fields && access.representation().IsDouble()) { 5318 if (FLAG_track_double_fields && access.representation().IsDouble()) {
5364 // load the heap number 5319 // load the heap number
5365 HLoadNamedField* heap_number = 5320 HLoadNamedField* heap_number = Add<HLoadNamedField>(
5366 AddLoad(object, access.WithRepresentation(Representation::Tagged())); 5321 object, access.WithRepresentation(Representation::Tagged()));
5367 heap_number->set_type(HType::HeapNumber()); 5322 heap_number->set_type(HType::HeapNumber());
5368 // load the double value from it 5323 // load the double value from it
5369 return new(zone()) HLoadNamedField(heap_number, 5324 return New<HLoadNamedField>(heap_number,
5370 HObjectAccess::ForHeapNumberValue(), NULL); 5325 HObjectAccess::ForHeapNumberValue(),
5326 typecheck);
5371 } 5327 }
5372 return new(zone()) HLoadNamedField(object, access, NULL); 5328 return New<HLoadNamedField>(object, access, typecheck);
5373 } 5329 }
5374 5330
5375 5331
5332 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
5333 HValue* typecheck) {
5334 if (FLAG_fold_constants && object->IsConstant()) {
5335 HConstant* constant = HConstant::cast(object);
5336 if (constant->HasStringValue()) {
5337 return New<HConstant>(constant->StringValue()->length());
5338 }
5339 }
5340 return BuildLoadNamedField(
5341 object, HObjectAccess::ForStringLength(), typecheck);
5342 }
5343
5344
5376 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 5345 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
5377 HValue* object, 5346 HValue* object,
5378 Handle<String> name, 5347 Handle<String> name,
5379 Property* expr) { 5348 Property* expr) {
5380 if (expr->IsUninitialized()) { 5349 if (expr->IsUninitialized()) {
5381 Add<HDeoptimize>(Deoptimizer::SOFT); 5350 Add<HDeoptimize>(Deoptimizer::SOFT);
5382 } 5351 }
5383 HValue* context = environment()->LookupContext(); 5352 HValue* context = environment()->context();
5384 return new(zone()) HLoadNamedGeneric(context, object, name); 5353 return new(zone()) HLoadNamedGeneric(context, object, name);
5385 } 5354 }
5386 5355
5387 5356
5388 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( 5357 HInstruction* HOptimizedGraphBuilder::BuildCallGetter(
5389 HValue* object, 5358 HValue* object,
5390 Handle<Map> map, 5359 Handle<Map> map,
5391 Handle<JSFunction> getter, 5360 Handle<JSFunction> getter,
5392 Handle<JSObject> holder) { 5361 Handle<JSObject> holder) {
5393 AddCheckConstantFunction(holder, object, map); 5362 AddCheckConstantFunction(holder, object, map);
5394 Add<HPushArgument>(object); 5363 Add<HPushArgument>(object);
5395 return new(zone()) HCallConstantFunction(getter, 1); 5364 return new(zone()) HCallConstantFunction(getter, 1);
5396 } 5365 }
5397 5366
5398 5367
5399 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( 5368 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
5400 HValue* object, 5369 HValue* object,
5401 Handle<String> name, 5370 Handle<String> name,
5402 Property* expr, 5371 Property* expr,
5403 Handle<Map> map) { 5372 Handle<Map> map) {
5404 // Handle a load from a known field. 5373 // Handle a load from a known field.
5405 ASSERT(!map->is_dictionary_map()); 5374 ASSERT(!map->is_dictionary_map());
5406 5375
5407 // Handle access to various length properties 5376 // Handle access to various length properties
5408 if (name->Equals(isolate()->heap()->length_string())) { 5377 if (name->Equals(isolate()->heap()->length_string())) {
5409 if (map->instance_type() == JS_ARRAY_TYPE) { 5378 if (map->instance_type() == JS_ARRAY_TYPE) {
5410 AddCheckMapsWithTransitions(object, map); 5379 AddCheckMap(object, map);
5411 return new(zone()) HLoadNamedField(object, 5380 return New<HLoadNamedField>(object,
5412 HObjectAccess::ForArrayLength(map->elements_kind())); 5381 HObjectAccess::ForArrayLength(map->elements_kind()));
5413 } 5382 }
5414 } 5383 }
5415 5384
5416 LookupResult lookup(isolate()); 5385 LookupResult lookup(isolate());
5417 map->LookupDescriptor(NULL, *name, &lookup); 5386 map->LookupDescriptor(NULL, *name, &lookup);
5418 if (lookup.IsField()) { 5387 if (lookup.IsField()) {
5419 AddCheckMap(object, map); 5388 AddCheckMap(object, map);
5420 return BuildLoadNamedField(object, 5389 return BuildLoadNamedField(object,
5421 HObjectAccess::ForField(map, &lookup, name)); 5390 HObjectAccess::ForField(map, &lookup, name));
5422 } 5391 }
5423 5392
5424 // Handle a load of a constant known function. 5393 // Handle a load of a constant known function.
5425 if (lookup.IsConstant()) { 5394 if (lookup.IsConstant()) {
5426 AddCheckMap(object, map); 5395 AddCheckMap(object, map);
5427 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); 5396 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
5428 return new(zone()) HConstant(constant); 5397 return New<HConstant>(constant);
5429 } 5398 }
5430 5399
5431 // Handle a load from a known field somewhere in the prototype chain. 5400 // Handle a load from a known field somewhere in the prototype chain.
5432 LookupInPrototypes(map, name, &lookup); 5401 LookupInPrototypes(map, name, &lookup);
5433 if (lookup.IsField()) { 5402 if (lookup.IsField()) {
5434 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5403 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5435 Handle<JSObject> holder(lookup.holder()); 5404 Handle<JSObject> holder(lookup.holder());
5436 Handle<Map> holder_map(holder->map()); 5405 Handle<Map> holder_map(holder->map());
5437 AddCheckMap(object, map); 5406 AddCheckMap(object, map);
5438 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); 5407 Add<HCheckPrototypeMaps>(prototype, holder, top_info());
5439 HValue* holder_value = Add<HConstant>(holder); 5408 HValue* holder_value = Add<HConstant>(holder);
5440 return BuildLoadNamedField(holder_value, 5409 return BuildLoadNamedField(holder_value,
5441 HObjectAccess::ForField(holder_map, &lookup, name)); 5410 HObjectAccess::ForField(holder_map, &lookup, name));
5442 } 5411 }
5443 5412
5444 // Handle a load of a constant function somewhere in the prototype chain. 5413 // Handle a load of a constant function somewhere in the prototype chain.
5445 if (lookup.IsConstant()) { 5414 if (lookup.IsConstant()) {
5446 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5415 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5447 Handle<JSObject> holder(lookup.holder()); 5416 Handle<JSObject> holder(lookup.holder());
5448 Handle<Map> holder_map(holder->map()); 5417 Handle<Map> holder_map(holder->map());
5449 AddCheckMap(object, map); 5418 AddCheckMap(object, map);
5450 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); 5419 Add<HCheckPrototypeMaps>(prototype, holder, top_info());
5451 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); 5420 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
5452 return new(zone()) HConstant(constant); 5421 return New<HConstant>(constant);
5453 } 5422 }
5454 5423
5455 // No luck, do a generic load. 5424 // No luck, do a generic load.
5456 return BuildLoadNamedGeneric(object, name, expr); 5425 return BuildLoadNamedGeneric(object, name, expr);
5457 } 5426 }
5458 5427
5459 5428
5460 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5429 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
5461 HValue* key) { 5430 HValue* key) {
5462 HValue* context = environment()->LookupContext(); 5431 HValue* context = environment()->context();
5463 return new(zone()) HLoadKeyedGeneric(context, object, key); 5432 return new(zone()) HLoadKeyedGeneric(context, object, key);
5464 } 5433 }
5465 5434
5466 5435
5467 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( 5436 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
5468 HValue* object, 5437 HValue* object,
5469 HValue* key, 5438 HValue* key,
5470 HValue* val, 5439 HValue* val,
5471 HValue* dependency, 5440 HValue* dependency,
5472 Handle<Map> map, 5441 Handle<Map> map,
5473 bool is_store, 5442 bool is_store,
5474 KeyedAccessStoreMode store_mode) { 5443 KeyedAccessStoreMode store_mode) {
5475 HCheckMaps* mapcheck = HCheckMaps::New( 5444 HCheckMaps* mapcheck = Add<HCheckMaps>(object, map, top_info(), dependency);
5476 object, map, zone(), top_info(), dependency);
5477 AddInstruction(mapcheck);
5478 if (dependency) { 5445 if (dependency) {
5479 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 5446 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
5480 } 5447 }
5481 5448
5482 // Loads from a "stock" fast holey double arrays can elide the hole check. 5449 // Loads from a "stock" fast holey double arrays can elide the hole check.
5483 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5450 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
5484 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 5451 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
5485 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 5452 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
5486 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 5453 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
5487 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 5454 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
5488 Add<HCheckPrototypeMaps>(prototype, object_prototype, zone(), top_info()); 5455 Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info());
5489 load_mode = ALLOW_RETURN_HOLE; 5456 load_mode = ALLOW_RETURN_HOLE;
5490 graph()->MarkDependsOnEmptyArrayProtoElements(); 5457 graph()->MarkDependsOnEmptyArrayProtoElements();
5491 } 5458 }
5492 5459
5493 return BuildUncheckedMonomorphicElementAccess( 5460 return BuildUncheckedMonomorphicElementAccess(
5494 object, key, val, 5461 object, key, val,
5495 mapcheck, map->instance_type() == JS_ARRAY_TYPE, 5462 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
5496 map->elements_kind(), is_store, load_mode, store_mode); 5463 map->elements_kind(), is_store, load_mode, store_mode);
5497 } 5464 }
5498 5465
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5535 // Remember the most general elements kind, the code for its load will 5502 // Remember the most general elements kind, the code for its load will
5536 // properly handle all of the more specific cases. 5503 // properly handle all of the more specific cases.
5537 if ((i == 0) || IsMoreGeneralElementsKindTransition( 5504 if ((i == 0) || IsMoreGeneralElementsKindTransition(
5538 most_general_consolidated_map->elements_kind(), 5505 most_general_consolidated_map->elements_kind(),
5539 map->elements_kind())) { 5506 map->elements_kind())) {
5540 most_general_consolidated_map = map; 5507 most_general_consolidated_map = map;
5541 } 5508 }
5542 } 5509 }
5543 if (!has_double_maps && !has_smi_or_object_maps) return NULL; 5510 if (!has_double_maps && !has_smi_or_object_maps) return NULL;
5544 5511
5545 HCheckMaps* check_maps = HCheckMaps::New(object, maps, zone()); 5512 HCheckMaps* check_maps = Add<HCheckMaps>(object, maps);
5546 AddInstruction(check_maps);
5547 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 5513 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
5548 object, key, val, check_maps, 5514 object, key, val, check_maps,
5549 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 5515 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
5550 most_general_consolidated_map->elements_kind(), 5516 most_general_consolidated_map->elements_kind(),
5551 false, NEVER_RETURN_HOLE, STANDARD_STORE); 5517 false, NEVER_RETURN_HOLE, STANDARD_STORE);
5552 return instr; 5518 return instr;
5553 } 5519 }
5554 5520
5555 5521
5556 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 5522 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
5601 5567
5602 MapHandleList untransitionable_maps(maps->length()); 5568 MapHandleList untransitionable_maps(maps->length());
5603 HTransitionElementsKind* transition = NULL; 5569 HTransitionElementsKind* transition = NULL;
5604 for (int i = 0; i < maps->length(); ++i) { 5570 for (int i = 0; i < maps->length(); ++i) {
5605 Handle<Map> map = maps->at(i); 5571 Handle<Map> map = maps->at(i);
5606 ASSERT(map->IsMap()); 5572 ASSERT(map->IsMap());
5607 if (!transition_target.at(i).is_null()) { 5573 if (!transition_target.at(i).is_null()) {
5608 ASSERT(Map::IsValidElementsTransition( 5574 ASSERT(Map::IsValidElementsTransition(
5609 map->elements_kind(), 5575 map->elements_kind(),
5610 transition_target.at(i)->elements_kind())); 5576 transition_target.at(i)->elements_kind()));
5611 HValue* context = environment()->LookupContext(); 5577 transition = Add<HTransitionElementsKind>(object, map,
5612 transition = Add<HTransitionElementsKind>(context, object, map,
5613 transition_target.at(i)); 5578 transition_target.at(i));
5614 } else { 5579 } else {
5615 untransitionable_maps.Add(map); 5580 untransitionable_maps.Add(map);
5616 } 5581 }
5617 } 5582 }
5618 5583
5619 // If only one map is left after transitioning, handle this case 5584 // If only one map is left after transitioning, handle this case
5620 // monomorphically. 5585 // monomorphically.
5621 ASSERT(untransitionable_maps.length() >= 1); 5586 ASSERT(untransitionable_maps.length() >= 1);
5622 if (untransitionable_maps.length() == 1) { 5587 if (untransitionable_maps.length() == 1) {
(...skipping 25 matching lines...) Expand all
5648 HBasicBlock* other_map = graph()->CreateBasicBlock(); 5613 HBasicBlock* other_map = graph()->CreateBasicBlock();
5649 HCompareMap* mapcompare = 5614 HCompareMap* mapcompare =
5650 new(zone()) HCompareMap(object, map, this_map, other_map); 5615 new(zone()) HCompareMap(object, map, this_map, other_map);
5651 current_block()->Finish(mapcompare); 5616 current_block()->Finish(mapcompare);
5652 5617
5653 set_current_block(this_map); 5618 set_current_block(this_map);
5654 HInstruction* checked_key = NULL; 5619 HInstruction* checked_key = NULL;
5655 HInstruction* access = NULL; 5620 HInstruction* access = NULL;
5656 if (IsFastElementsKind(elements_kind)) { 5621 if (IsFastElementsKind(elements_kind)) {
5657 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { 5622 if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
5658 AddInstruction(HCheckMaps::New( 5623 Add<HCheckMaps>(
5659 elements, isolate()->factory()->fixed_array_map(), 5624 elements, isolate()->factory()->fixed_array_map(),
5660 zone(), top_info(), mapcompare)); 5625 top_info(), mapcompare);
5661 } 5626 }
5662 if (map->instance_type() == JS_ARRAY_TYPE) { 5627 if (map->instance_type() == JS_ARRAY_TYPE) {
5663 HInstruction* length = AddLoad( 5628 HInstruction* length = Add<HLoadNamedField>(
5664 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); 5629 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare);
5665 checked_key = Add<HBoundsCheck>(key, length); 5630 checked_key = Add<HBoundsCheck>(key, length);
5666 } else { 5631 } else {
5667 HInstruction* length = AddLoadFixedArrayLength(elements); 5632 HInstruction* length = AddLoadFixedArrayLength(elements);
5668 checked_key = Add<HBoundsCheck>(key, length); 5633 checked_key = Add<HBoundsCheck>(key, length);
5669 } 5634 }
5670 access = AddFastElementAccess( 5635 access = AddFastElementAccess(
5671 elements, checked_key, val, mapcompare, 5636 elements, checked_key, val, mapcompare,
5672 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); 5637 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE);
5673 } else if (IsDictionaryElementsKind(elements_kind)) { 5638 } else if (IsDictionaryElementsKind(elements_kind)) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
5749 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5714 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5750 *has_side_effects = instr->HasObservableSideEffects(); 5715 *has_side_effects = instr->HasObservableSideEffects();
5751 return instr; 5716 return instr;
5752 } 5717 }
5753 5718
5754 5719
5755 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( 5720 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
5756 HValue* object, 5721 HValue* object,
5757 HValue* key, 5722 HValue* key,
5758 HValue* value) { 5723 HValue* value) {
5759 HValue* context = environment()->LookupContext(); 5724 HValue* context = environment()->context();
5760 return new(zone()) HStoreKeyedGeneric( 5725 return new(zone()) HStoreKeyedGeneric(
5761 context, 5726 context,
5762 object, 5727 object,
5763 key, 5728 key,
5764 value, 5729 value,
5765 function_strict_mode_flag()); 5730 function_strict_mode_flag());
5766 } 5731 }
5767 5732
5768 5733
5769 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { 5734 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
5770 // Outermost function already has arguments on the stack. 5735 // Outermost function already has arguments on the stack.
5771 if (function_state()->outer() == NULL) return; 5736 if (function_state()->outer() == NULL) return;
5772 5737
5773 if (function_state()->arguments_pushed()) return; 5738 if (function_state()->arguments_pushed()) return;
5774 5739
5775 // Push arguments when entering inlined function. 5740 // Push arguments when entering inlined function.
5776 HEnterInlined* entry = function_state()->entry(); 5741 HEnterInlined* entry = function_state()->entry();
5777 entry->set_arguments_pushed(); 5742 entry->set_arguments_pushed();
5778 5743
5779 HArgumentsObject* arguments = entry->arguments_object(); 5744 HArgumentsObject* arguments = entry->arguments_object();
5780 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); 5745 const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
5781 5746
5782 HInstruction* insert_after = entry; 5747 HInstruction* insert_after = entry;
5783 for (int i = 0; i < arguments_values->length(); i++) { 5748 for (int i = 0; i < arguments_values->length(); i++) {
5784 HValue* argument = arguments_values->at(i); 5749 HValue* argument = arguments_values->at(i);
5785 HInstruction* push_argument = new(zone()) HPushArgument(argument); 5750 HInstruction* push_argument = New<HPushArgument>(argument);
5786 push_argument->InsertAfter(insert_after); 5751 push_argument->InsertAfter(insert_after);
5787 insert_after = push_argument; 5752 insert_after = push_argument;
5788 } 5753 }
5789 5754
5790 HArgumentsElements* arguments_elements = 5755 HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
5791 new(zone()) HArgumentsElements(true);
5792 arguments_elements->ClearFlag(HValue::kUseGVN); 5756 arguments_elements->ClearFlag(HValue::kUseGVN);
5793 arguments_elements->InsertAfter(insert_after); 5757 arguments_elements->InsertAfter(insert_after);
5794 function_state()->set_arguments_elements(arguments_elements); 5758 function_state()->set_arguments_elements(arguments_elements);
5795 } 5759 }
5796 5760
5797 5761
5798 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { 5762 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
5799 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 5763 VariableProxy* proxy = expr->obj()->AsVariableProxy();
5800 if (proxy == NULL) return false; 5764 if (proxy == NULL) return false;
5801 if (!proxy->var()->IsStackAllocated()) return false; 5765 if (!proxy->var()->IsStackAllocated()) return false;
5802 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 5766 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
5803 return false; 5767 return false;
5804 } 5768 }
5805 5769
5806 HInstruction* result = NULL; 5770 HInstruction* result = NULL;
5807 if (expr->key()->IsPropertyName()) { 5771 if (expr->key()->IsPropertyName()) {
5808 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 5772 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5809 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; 5773 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false;
5810 5774
5811 if (function_state()->outer() == NULL) { 5775 if (function_state()->outer() == NULL) {
5812 HInstruction* elements = Add<HArgumentsElements>(false); 5776 HInstruction* elements = Add<HArgumentsElements>(false);
5813 result = new(zone()) HArgumentsLength(elements); 5777 result = New<HArgumentsLength>(elements);
5814 } else { 5778 } else {
5815 // Number of arguments without receiver. 5779 // Number of arguments without receiver.
5816 int argument_count = environment()-> 5780 int argument_count = environment()->
5817 arguments_environment()->parameter_count() - 1; 5781 arguments_environment()->parameter_count() - 1;
5818 result = new(zone()) HConstant(argument_count); 5782 result = New<HConstant>(argument_count);
5819 } 5783 }
5820 } else { 5784 } else {
5821 Push(graph()->GetArgumentsObject()); 5785 Push(graph()->GetArgumentsObject());
5822 VisitForValue(expr->key()); 5786 VisitForValue(expr->key());
5823 if (HasStackOverflow() || current_block() == NULL) return true; 5787 if (HasStackOverflow() || current_block() == NULL) return true;
5824 HValue* key = Pop(); 5788 HValue* key = Pop();
5825 Drop(1); // Arguments object. 5789 Drop(1); // Arguments object.
5826 if (function_state()->outer() == NULL) { 5790 if (function_state()->outer() == NULL) {
5827 HInstruction* elements = Add<HArgumentsElements>(false); 5791 HInstruction* elements = Add<HArgumentsElements>(false);
5828 HInstruction* length = Add<HArgumentsLength>(elements); 5792 HInstruction* length = Add<HArgumentsLength>(elements);
(...skipping 22 matching lines...) Expand all
5851 ASSERT(current_block()->HasPredecessor()); 5815 ASSERT(current_block()->HasPredecessor());
5852 5816
5853 if (TryArgumentsAccess(expr)) return; 5817 if (TryArgumentsAccess(expr)) return;
5854 5818
5855 CHECK_ALIVE(VisitForValue(expr->obj())); 5819 CHECK_ALIVE(VisitForValue(expr->obj()));
5856 5820
5857 HInstruction* instr = NULL; 5821 HInstruction* instr = NULL;
5858 if (expr->IsStringLength()) { 5822 if (expr->IsStringLength()) {
5859 HValue* string = Pop(); 5823 HValue* string = Pop();
5860 BuildCheckHeapObject(string); 5824 BuildCheckHeapObject(string);
5861 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); 5825 HInstruction* checkstring =
5862 instr = HStringLength::New(zone(), string); 5826 AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
5827 instr = BuildLoadStringLength(string, checkstring);
5863 } else if (expr->IsStringAccess()) { 5828 } else if (expr->IsStringAccess()) {
5864 CHECK_ALIVE(VisitForValue(expr->key())); 5829 CHECK_ALIVE(VisitForValue(expr->key()));
5865 HValue* index = Pop(); 5830 HValue* index = Pop();
5866 HValue* string = Pop(); 5831 HValue* string = Pop();
5867 HValue* context = environment()->LookupContext(); 5832 HValue* context = environment()->context();
5868 HInstruction* char_code = 5833 HInstruction* char_code =
5869 BuildStringCharCodeAt(context, string, index); 5834 BuildStringCharCodeAt(string, index);
5870 AddInstruction(char_code); 5835 AddInstruction(char_code);
5871 instr = HStringCharFromCode::New(zone(), context, char_code); 5836 instr = HStringCharFromCode::New(zone(), context, char_code);
5872 5837
5873 } else if (expr->IsFunctionPrototype()) { 5838 } else if (expr->IsFunctionPrototype()) {
5874 HValue* function = Pop(); 5839 HValue* function = Pop();
5875 BuildCheckHeapObject(function); 5840 BuildCheckHeapObject(function);
5876 instr = new(zone()) HLoadFunctionPrototype(function); 5841 instr = new(zone()) HLoadFunctionPrototype(function);
5877 5842
5878 } else if (expr->key()->IsPropertyName()) { 5843 } else if (expr->key()->IsPropertyName()) {
5879 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 5844 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5930 } 5895 }
5931 instr->set_position(expr->position()); 5896 instr->set_position(expr->position());
5932 return ast_context()->ReturnInstruction(instr, expr->id()); 5897 return ast_context()->ReturnInstruction(instr, expr->id());
5933 } 5898 }
5934 5899
5935 5900
5936 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, 5901 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
5937 Handle<Map> receiver_map) { 5902 Handle<Map> receiver_map) {
5938 if (!holder.is_null()) { 5903 if (!holder.is_null()) {
5939 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 5904 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
5940 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); 5905 Add<HCheckPrototypeMaps>(prototype, holder, top_info());
5941 } 5906 }
5942 } 5907 }
5943 5908
5944 5909
5945 void HOptimizedGraphBuilder::AddCheckConstantFunction( 5910 void HOptimizedGraphBuilder::AddCheckConstantFunction(
5946 Handle<JSObject> holder, 5911 Handle<JSObject> holder,
5947 HValue* receiver, 5912 HValue* receiver,
5948 Handle<Map> receiver_map) { 5913 Handle<Map> receiver_map) {
5949 // Constant functions have the nice property that the map will change if they 5914 // Constant functions have the nice property that the map will change if they
5950 // are overwritten. Therefore it is enough to check the map of the holder and 5915 // are overwritten. Therefore it is enough to check the map of the holder and
5951 // its prototypes. 5916 // its prototypes.
5952 AddCheckMapsWithTransitions(receiver, receiver_map); 5917 AddCheckMap(receiver, receiver_map);
5953 AddCheckPrototypeMaps(holder, receiver_map); 5918 AddCheckPrototypeMaps(holder, receiver_map);
5954 } 5919 }
5955 5920
5956 5921
5957 class FunctionSorter { 5922 class FunctionSorter {
5958 public: 5923 public:
5959 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } 5924 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { }
5960 FunctionSorter(int index, int ticks, int ast_length, int src_length) 5925 FunctionSorter(int index, int ticks, int ast_length, int src_length)
5961 : index_(index), 5926 : index_(index),
5962 ticks_(ticks), 5927 ticks_(ticks),
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5999 Handle<Object> prototype(map->prototype(), isolate()); 5964 Handle<Object> prototype(map->prototype(), isolate());
6000 for (int count = 1; count < types->length(); ++count) { 5965 for (int count = 1; count < types->length(); ++count) {
6001 Handle<Map> test_map(types->at(count)); 5966 Handle<Map> test_map(types->at(count));
6002 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false; 5967 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false;
6003 if (test_map->prototype() != *prototype) return false; 5968 if (test_map->prototype() != *prototype) return false;
6004 } 5969 }
6005 5970
6006 if (!expr->ComputeTarget(map, name)) return false; 5971 if (!expr->ComputeTarget(map, name)) return false;
6007 5972
6008 BuildCheckHeapObject(receiver); 5973 BuildCheckHeapObject(receiver);
6009 AddInstruction(HCheckMaps::New(receiver, types, zone())); 5974 Add<HCheckMaps>(receiver, types);
6010 AddCheckPrototypeMaps(expr->holder(), map); 5975 AddCheckPrototypeMaps(expr->holder(), map);
6011 if (FLAG_trace_inlining) { 5976 if (FLAG_trace_inlining) {
6012 Handle<JSFunction> caller = current_info()->closure(); 5977 Handle<JSFunction> caller = current_info()->closure();
6013 SmartArrayPointer<char> caller_name = 5978 SmartArrayPointer<char> caller_name =
6014 caller->shared()->DebugName()->ToCString(); 5979 caller->shared()->DebugName()->ToCString();
6015 PrintF("Trying to inline the polymorphic call to %s from %s\n", 5980 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6016 *name->ToCString(), *caller_name); 5981 *name->ToCString(), *caller_name);
6017 } 5982 }
6018 5983
6019 if (!TryInlineCall(expr)) { 5984 if (!TryInlineCall(expr)) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
6155 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6120 // Finish up. Unconditionally deoptimize if we've handled all the maps we
6156 // know about and do not want to handle ones we've never seen. Otherwise 6121 // know about and do not want to handle ones we've never seen. Otherwise
6157 // use a generic IC. 6122 // use a generic IC.
6158 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 6123 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
6159 // Because the deopt may be the only path in the polymorphic call, make sure 6124 // Because the deopt may be the only path in the polymorphic call, make sure
6160 // that the environment stack matches the depth on deopt that it otherwise 6125 // that the environment stack matches the depth on deopt that it otherwise
6161 // would have had after a successful call. 6126 // would have had after a successful call.
6162 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); 6127 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1));
6163 FinishExitWithHardDeoptimization(join); 6128 FinishExitWithHardDeoptimization(join);
6164 } else { 6129 } else {
6165 HValue* context = environment()->LookupContext(); 6130 HValue* context = environment()->context();
6166 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); 6131 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
6167 call->set_position(expr->position()); 6132 call->set_position(expr->position());
6168 PreProcessCall(call); 6133 PreProcessCall(call);
6169 6134
6170 if (join != NULL) { 6135 if (join != NULL) {
6171 AddInstruction(call); 6136 AddInstruction(call);
6172 if (!ast_context()->IsEffect()) Push(call); 6137 if (!ast_context()->IsEffect()) Push(call);
6173 current_block()->Goto(join); 6138 current_block()->Goto(join);
6174 } else { 6139 } else {
6175 return ast_context()->ReturnInstruction(call, expr->id()); 6140 return ast_context()->ReturnInstruction(call, expr->id());
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
6302 return false; 6267 return false;
6303 } 6268 }
6304 6269
6305 // Parse and allocate variables. 6270 // Parse and allocate variables.
6306 CompilationInfo target_info(target, zone()); 6271 CompilationInfo target_info(target, zone());
6307 Handle<SharedFunctionInfo> target_shared(target->shared()); 6272 Handle<SharedFunctionInfo> target_shared(target->shared());
6308 if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) { 6273 if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
6309 if (target_info.isolate()->has_pending_exception()) { 6274 if (target_info.isolate()->has_pending_exception()) {
6310 // Parse or scope error, never optimize this function. 6275 // Parse or scope error, never optimize this function.
6311 SetStackOverflow(); 6276 SetStackOverflow();
6312 target_shared->DisableOptimization("parse/scope error"); 6277 target_shared->DisableOptimization(kParseScopeError);
6313 } 6278 }
6314 TraceInline(target, caller, "parse failure"); 6279 TraceInline(target, caller, "parse failure");
6315 return false; 6280 return false;
6316 } 6281 }
6317 6282
6318 if (target_info.scope()->num_heap_slots() > 0) { 6283 if (target_info.scope()->num_heap_slots() > 0) {
6319 TraceInline(target, caller, "target has context-allocated variables"); 6284 TraceInline(target, caller, "target has context-allocated variables");
6320 return false; 6285 return false;
6321 } 6286 }
6322 FunctionLiteral* function = target_info.function(); 6287 FunctionLiteral* function = target_info.function();
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
6421 Add<HSimulate>(return_id); 6386 Add<HSimulate>(return_id);
6422 current_block()->UpdateEnvironment(inner_env); 6387 current_block()->UpdateEnvironment(inner_env);
6423 HArgumentsObject* arguments_object = NULL; 6388 HArgumentsObject* arguments_object = NULL;
6424 6389
6425 // If the function uses arguments object create and bind one, also copy 6390 // If the function uses arguments object create and bind one, also copy
6426 // current arguments values to use them for materialization. 6391 // current arguments values to use them for materialization.
6427 if (function->scope()->arguments() != NULL) { 6392 if (function->scope()->arguments() != NULL) {
6428 ASSERT(function->scope()->arguments()->IsStackAllocated()); 6393 ASSERT(function->scope()->arguments()->IsStackAllocated());
6429 HEnvironment* arguments_env = inner_env->arguments_environment(); 6394 HEnvironment* arguments_env = inner_env->arguments_environment();
6430 int arguments_count = arguments_env->parameter_count(); 6395 int arguments_count = arguments_env->parameter_count();
6431 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); 6396 arguments_object = Add<HArgumentsObject>(arguments_count);
6432 inner_env->Bind(function->scope()->arguments(), arguments_object); 6397 inner_env->Bind(function->scope()->arguments(), arguments_object);
6433 for (int i = 0; i < arguments_count; i++) { 6398 for (int i = 0; i < arguments_count; i++) {
6434 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); 6399 arguments_object->AddArgument(arguments_env->Lookup(i), zone());
6435 } 6400 }
6436 } 6401 }
6437 6402
6438 HEnterInlined* enter_inlined = 6403 HEnterInlined* enter_inlined =
6439 Add<HEnterInlined>(target, arguments_count, function, 6404 Add<HEnterInlined>(target, arguments_count, function,
6440 function_state()->inlining_kind(), 6405 function_state()->inlining_kind(),
6441 function->scope()->arguments(), 6406 function->scope()->arguments(),
6442 arguments_object, undefined_receiver, zone()); 6407 arguments_object, undefined_receiver);
6443 function_state()->set_entry(enter_inlined); 6408 function_state()->set_entry(enter_inlined);
6444 6409
6445 VisitDeclarations(target_info.scope()->declarations()); 6410 VisitDeclarations(target_info.scope()->declarations());
6446 VisitStatements(function->body()); 6411 VisitStatements(function->body());
6447 if (HasStackOverflow()) { 6412 if (HasStackOverflow()) {
6448 // Bail out if the inline function did, as we cannot residualize a call 6413 // Bail out if the inline function did, as we cannot residualize a call
6449 // instead. 6414 // instead.
6450 TraceInline(target, caller, "inline graph construction failed"); 6415 TraceInline(target, caller, "inline graph construction failed");
6451 target_shared->DisableOptimization("inlining bailed out"); 6416 target_shared->DisableOptimization(kInliningBailedOut);
6452 inline_bailout_ = true; 6417 inline_bailout_ = true;
6453 delete target_state; 6418 delete target_state;
6454 return true; 6419 return true;
6455 } 6420 }
6456 6421
6457 // Update inlined nodes count. 6422 // Update inlined nodes count.
6458 inlined_count_ += nodes_added; 6423 inlined_count_ += nodes_added;
6459 6424
6460 Handle<Code> unoptimized_code(target_shared->code()); 6425 Handle<Code> unoptimized_code(target_shared->code());
6461 ASSERT(unoptimized_code->kind() == Code::FUNCTION); 6426 ASSERT(unoptimized_code->kind() == Code::FUNCTION);
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
6623 case kMathRound: 6588 case kMathRound:
6624 case kMathFloor: 6589 case kMathFloor:
6625 case kMathAbs: 6590 case kMathAbs:
6626 case kMathSqrt: 6591 case kMathSqrt:
6627 case kMathLog: 6592 case kMathLog:
6628 case kMathSin: 6593 case kMathSin:
6629 case kMathCos: 6594 case kMathCos:
6630 case kMathTan: 6595 case kMathTan:
6631 if (expr->arguments()->length() == 1) { 6596 if (expr->arguments()->length() == 1) {
6632 HValue* argument = Pop(); 6597 HValue* argument = Pop();
6633 HValue* context = environment()->LookupContext(); 6598 HValue* context = environment()->context();
6634 Drop(1); // Receiver. 6599 Drop(1); // Receiver.
6635 HInstruction* op = 6600 HInstruction* op =
6636 HUnaryMathOperation::New(zone(), context, argument, id); 6601 HUnaryMathOperation::New(zone(), context, argument, id);
6637 op->set_position(expr->position()); 6602 op->set_position(expr->position());
6638 if (drop_extra) Drop(1); // Optionally drop the function. 6603 if (drop_extra) Drop(1); // Optionally drop the function.
6639 ast_context()->ReturnInstruction(op, expr->id()); 6604 ast_context()->ReturnInstruction(op, expr->id());
6640 return true; 6605 return true;
6641 } 6606 }
6642 break; 6607 break;
6643 case kMathImul: 6608 case kMathImul:
6644 if (expr->arguments()->length() == 2) { 6609 if (expr->arguments()->length() == 2) {
6645 HValue* right = Pop(); 6610 HValue* right = Pop();
6646 HValue* left = Pop(); 6611 HValue* left = Pop();
6647 Drop(1); // Receiver. 6612 Drop(1); // Receiver.
6648 HValue* context = environment()->LookupContext(); 6613 HValue* context = environment()->context();
6649 HInstruction* op = HMul::NewImul(zone(), context, left, right); 6614 HInstruction* op = HMul::NewImul(zone(), context, left, right);
6650 if (drop_extra) Drop(1); // Optionally drop the function. 6615 if (drop_extra) Drop(1); // Optionally drop the function.
6651 ast_context()->ReturnInstruction(op, expr->id()); 6616 ast_context()->ReturnInstruction(op, expr->id());
6652 return true; 6617 return true;
6653 } 6618 }
6654 break; 6619 break;
6655 default: 6620 default:
6656 // Not supported for inlining yet. 6621 // Not supported for inlining yet.
6657 break; 6622 break;
6658 } 6623 }
(...skipping 10 matching lines...) Expand all
6669 // Try to inline calls like Math.* as operations in the calling function. 6634 // Try to inline calls like Math.* as operations in the calling function.
6670 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 6635 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
6671 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 6636 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
6672 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 6637 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
6673 switch (id) { 6638 switch (id) {
6674 case kStringCharCodeAt: 6639 case kStringCharCodeAt:
6675 case kStringCharAt: 6640 case kStringCharAt:
6676 if (argument_count == 2 && check_type == STRING_CHECK) { 6641 if (argument_count == 2 && check_type == STRING_CHECK) {
6677 HValue* index = Pop(); 6642 HValue* index = Pop();
6678 HValue* string = Pop(); 6643 HValue* string = Pop();
6679 HValue* context = environment()->LookupContext(); 6644 HValue* context = environment()->context();
6680 ASSERT(!expr->holder().is_null()); 6645 ASSERT(!expr->holder().is_null());
6681 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( 6646 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck(
6682 STRING_CHECK, expr->holder()->GetIsolate()), 6647 STRING_CHECK, expr->holder()->GetIsolate()),
6683 expr->holder(), zone(), top_info()); 6648 expr->holder(), top_info());
6684 HInstruction* char_code = 6649 HInstruction* char_code =
6685 BuildStringCharCodeAt(context, string, index); 6650 BuildStringCharCodeAt(string, index);
6686 if (id == kStringCharCodeAt) { 6651 if (id == kStringCharCodeAt) {
6687 ast_context()->ReturnInstruction(char_code, expr->id()); 6652 ast_context()->ReturnInstruction(char_code, expr->id());
6688 return true; 6653 return true;
6689 } 6654 }
6690 AddInstruction(char_code); 6655 AddInstruction(char_code);
6691 HInstruction* result = 6656 HInstruction* result =
6692 HStringCharFromCode::New(zone(), context, char_code); 6657 HStringCharFromCode::New(zone(), context, char_code);
6693 ast_context()->ReturnInstruction(result, expr->id()); 6658 ast_context()->ReturnInstruction(result, expr->id());
6694 return true; 6659 return true;
6695 } 6660 }
6696 break; 6661 break;
6697 case kStringFromCharCode: 6662 case kStringFromCharCode:
6698 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 6663 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
6699 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6664 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6700 HValue* argument = Pop(); 6665 HValue* argument = Pop();
6701 HValue* context = environment()->LookupContext(); 6666 HValue* context = environment()->context();
6702 Drop(1); // Receiver. 6667 Drop(1); // Receiver.
6703 HInstruction* result = 6668 HInstruction* result =
6704 HStringCharFromCode::New(zone(), context, argument); 6669 HStringCharFromCode::New(zone(), context, argument);
6705 ast_context()->ReturnInstruction(result, expr->id()); 6670 ast_context()->ReturnInstruction(result, expr->id());
6706 return true; 6671 return true;
6707 } 6672 }
6708 break; 6673 break;
6709 case kMathExp: 6674 case kMathExp:
6710 if (!FLAG_fast_math) break; 6675 if (!FLAG_fast_math) break;
6711 // Fall through if FLAG_fast_math. 6676 // Fall through if FLAG_fast_math.
6712 case kMathRound: 6677 case kMathRound:
6713 case kMathFloor: 6678 case kMathFloor:
6714 case kMathAbs: 6679 case kMathAbs:
6715 case kMathSqrt: 6680 case kMathSqrt:
6716 case kMathLog: 6681 case kMathLog:
6717 case kMathSin: 6682 case kMathSin:
6718 case kMathCos: 6683 case kMathCos:
6719 case kMathTan: 6684 case kMathTan:
6720 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 6685 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
6721 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6686 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6722 HValue* argument = Pop(); 6687 HValue* argument = Pop();
6723 HValue* context = environment()->LookupContext(); 6688 HValue* context = environment()->context();
6724 Drop(1); // Receiver. 6689 Drop(1); // Receiver.
6725 HInstruction* op = 6690 HInstruction* op =
6726 HUnaryMathOperation::New(zone(), context, argument, id); 6691 HUnaryMathOperation::New(zone(), context, argument, id);
6727 op->set_position(expr->position()); 6692 op->set_position(expr->position());
6728 ast_context()->ReturnInstruction(op, expr->id()); 6693 ast_context()->ReturnInstruction(op, expr->id());
6729 return true; 6694 return true;
6730 } 6695 }
6731 break; 6696 break;
6732 case kMathPow: 6697 case kMathPow:
6733 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 6698 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
6734 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6699 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6735 HValue* right = Pop(); 6700 HValue* right = Pop();
6736 HValue* left = Pop(); 6701 HValue* left = Pop();
6737 Pop(); // Pop receiver. 6702 Pop(); // Pop receiver.
6738 HValue* context = environment()->LookupContext(); 6703 HValue* context = environment()->context();
6739 HInstruction* result = NULL; 6704 HInstruction* result = NULL;
6740 // Use sqrt() if exponent is 0.5 or -0.5. 6705 // Use sqrt() if exponent is 0.5 or -0.5.
6741 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 6706 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
6742 double exponent = HConstant::cast(right)->DoubleValue(); 6707 double exponent = HConstant::cast(right)->DoubleValue();
6743 if (exponent == 0.5) { 6708 if (exponent == 0.5) {
6744 result = 6709 result =
6745 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); 6710 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
6746 } else if (exponent == -0.5) { 6711 } else if (exponent == -0.5) {
6747 HValue* one = graph()->GetConstant1(); 6712 HValue* one = graph()->GetConstant1();
6748 HInstruction* sqrt = 6713 HInstruction* sqrt =
6749 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); 6714 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
6750 AddInstruction(sqrt); 6715 AddInstruction(sqrt);
6751 // MathPowHalf doesn't have side effects so there's no need for 6716 // MathPowHalf doesn't have side effects so there's no need for
6752 // an environment simulation here. 6717 // an environment simulation here.
6753 ASSERT(!sqrt->HasObservableSideEffects()); 6718 ASSERT(!sqrt->HasObservableSideEffects());
6754 result = HDiv::New(zone(), context, one, sqrt); 6719 result = HDiv::New(zone(), context, one, sqrt);
6755 } else if (exponent == 2.0) { 6720 } else if (exponent == 2.0) {
6756 result = HMul::New(zone(), context, left, left); 6721 result = HMul::New(zone(), context, left, left);
6757 } 6722 }
6758 } else if (right->EqualsInteger32Constant(2)) { 6723 } else if (right->EqualsInteger32Constant(2)) {
6759 result = HMul::New(zone(), context, left, left); 6724 result = HMul::New(zone(), context, left, left);
6760 } 6725 }
6761 6726
6762 if (result == NULL) { 6727 if (result == NULL) {
6763 result = HPower::New(zone(), left, right); 6728 result = HPower::New(zone(), context, left, right);
6764 } 6729 }
6765 ast_context()->ReturnInstruction(result, expr->id()); 6730 ast_context()->ReturnInstruction(result, expr->id());
6766 return true; 6731 return true;
6767 } 6732 }
6768 break; 6733 break;
6769 case kMathRandom: 6734 case kMathRandom:
6770 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { 6735 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
6771 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6736 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6772 Drop(1); // Receiver. 6737 Drop(1); // Receiver.
6773 HValue* context = environment()->LookupContext(); 6738 HGlobalObject* global_object = Add<HGlobalObject>();
6774 HGlobalObject* global_object = Add<HGlobalObject>(context);
6775 HRandom* result = new(zone()) HRandom(global_object); 6739 HRandom* result = new(zone()) HRandom(global_object);
6776 ast_context()->ReturnInstruction(result, expr->id()); 6740 ast_context()->ReturnInstruction(result, expr->id());
6777 return true; 6741 return true;
6778 } 6742 }
6779 break; 6743 break;
6780 case kMathMax: 6744 case kMathMax:
6781 case kMathMin: 6745 case kMathMin:
6782 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 6746 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
6783 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6747 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6784 HValue* right = Pop(); 6748 HValue* right = Pop();
6785 HValue* left = Pop(); 6749 HValue* left = Pop();
6786 Drop(1); // Receiver. 6750 Drop(1); // Receiver.
6787 HValue* context = environment()->LookupContext(); 6751 HValue* context = environment()->context();
6788 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin 6752 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
6789 : HMathMinMax::kMathMax; 6753 : HMathMinMax::kMathMax;
6790 HInstruction* result = 6754 HInstruction* result =
6791 HMathMinMax::New(zone(), context, left, right, op); 6755 HMathMinMax::New(zone(), context, left, right, op);
6792 ast_context()->ReturnInstruction(result, expr->id()); 6756 ast_context()->ReturnInstruction(result, expr->id());
6793 return true; 6757 return true;
6794 } 6758 }
6795 break; 6759 break;
6796 case kMathImul: 6760 case kMathImul:
6797 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 6761 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
6798 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6762 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
6799 HValue* right = Pop(); 6763 HValue* right = Pop();
6800 HValue* left = Pop(); 6764 HValue* left = Pop();
6801 Drop(1); // Receiver. 6765 Drop(1); // Receiver.
6802 HValue* context = environment()->LookupContext(); 6766 HValue* context = environment()->context();
6803 HInstruction* result = HMul::NewImul(zone(), context, left, right); 6767 HInstruction* result = HMul::NewImul(zone(), context, left, right);
6804 ast_context()->ReturnInstruction(result, expr->id()); 6768 ast_context()->ReturnInstruction(result, expr->id());
6805 return true; 6769 return true;
6806 } 6770 }
6807 break; 6771 break;
6808 default: 6772 default:
6809 // Not yet supported for inlining. 6773 // Not yet supported for inlining.
6810 break; 6774 break;
6811 } 6775 }
6812 return false; 6776 return false;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
6876 6840
6877 Handle<JSFunction> known_function; 6841 Handle<JSFunction> known_function;
6878 if (function->IsConstant()) { 6842 if (function->IsConstant()) {
6879 HConstant* constant_function = HConstant::cast(function); 6843 HConstant* constant_function = HConstant::cast(function);
6880 known_function = Handle<JSFunction>::cast(constant_function->handle()); 6844 known_function = Handle<JSFunction>::cast(constant_function->handle());
6881 int args_count = arguments_count - 1; // Excluding receiver. 6845 int args_count = arguments_count - 1; // Excluding receiver.
6882 if (TryInlineApply(known_function, expr, args_count)) return true; 6846 if (TryInlineApply(known_function, expr, args_count)) return true;
6883 } 6847 }
6884 6848
6885 Drop(arguments_count - 1); 6849 Drop(arguments_count - 1);
6886 PushAndAdd(new(zone()) HPushArgument(Pop())); 6850 PushAndAdd(New<HPushArgument>(Pop()));
6887 for (int i = 1; i < arguments_count; i++) { 6851 for (int i = 1; i < arguments_count; i++) {
6888 PushAndAdd(new(zone()) HPushArgument(arguments_values->at(i))); 6852 PushAndAdd(New<HPushArgument>(arguments_values->at(i)));
6889 } 6853 }
6890 6854
6891 HValue* context = environment()->LookupContext(); 6855 HValue* context = environment()->context();
6892 HInvokeFunction* call = new(zone()) HInvokeFunction( 6856 HInvokeFunction* call = new(zone()) HInvokeFunction(
6893 context, 6857 context,
6894 function, 6858 function,
6895 known_function, 6859 known_function,
6896 arguments_count); 6860 arguments_count);
6897 Drop(arguments_count); 6861 Drop(arguments_count);
6898 call->set_position(expr->position()); 6862 call->set_position(expr->position());
6899 ast_context()->ReturnInstruction(call, expr->id()); 6863 ast_context()->ReturnInstruction(call, expr->id());
6900 return true; 6864 return true;
6901 } 6865 }
6902 } 6866 }
6903 6867
6904 6868
6905 // Checks if all maps in |types| are from the same family, i.e., are elements
6906 // transitions of each other. Returns either NULL if they are not from the same
6907 // family, or a Map* indicating the map with the first elements kind of the
6908 // family that is in the list.
6909 static Map* CheckSameElementsFamily(SmallMapList* types) {
6910 if (types->length() <= 1) return NULL;
6911 // Check if all maps belong to the same transition family.
6912 Map* kinds[kFastElementsKindCount];
6913 Map* first_map = *types->first();
6914 ElementsKind first_kind = first_map->elements_kind();
6915 if (!IsFastElementsKind(first_kind)) return NULL;
6916 int first_index = GetSequenceIndexFromFastElementsKind(first_kind);
6917 int last_index = first_index;
6918
6919 for (int i = 0; i < kFastElementsKindCount; i++) kinds[i] = NULL;
6920
6921 kinds[first_index] = first_map;
6922
6923 for (int i = 1; i < types->length(); ++i) {
6924 Map* map = *types->at(i);
6925 ElementsKind elements_kind = map->elements_kind();
6926 if (!IsFastElementsKind(elements_kind)) return NULL;
6927 int index = GetSequenceIndexFromFastElementsKind(elements_kind);
6928 if (index < first_index) {
6929 first_index = index;
6930 } else if (index > last_index) {
6931 last_index = index;
6932 } else if (kinds[index] != map) {
6933 return NULL;
6934 }
6935 kinds[index] = map;
6936 }
6937
6938 Map* current = kinds[first_index];
6939 for (int i = first_index + 1; i <= last_index; i++) {
6940 Map* next = kinds[i];
6941 if (next != NULL) {
6942 ElementsKind current_kind = next->elements_kind();
6943 if (next != current->LookupElementsTransitionMap(current_kind)) {
6944 return NULL;
6945 }
6946 current = next;
6947 }
6948 }
6949
6950 return kinds[first_index];
6951 }
6952
6953
6954 void HOptimizedGraphBuilder::VisitCall(Call* expr) { 6869 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
6955 ASSERT(!HasStackOverflow()); 6870 ASSERT(!HasStackOverflow());
6956 ASSERT(current_block() != NULL); 6871 ASSERT(current_block() != NULL);
6957 ASSERT(current_block()->HasPredecessor()); 6872 ASSERT(current_block()->HasPredecessor());
6958 Expression* callee = expr->expression(); 6873 Expression* callee = expr->expression();
6959 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 6874 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
6960 HInstruction* call = NULL; 6875 HInstruction* call = NULL;
6961 6876
6962 Property* prop = callee->AsProperty(); 6877 Property* prop = callee->AsProperty();
6963 if (prop != NULL) { 6878 if (prop != NULL) {
6964 if (!prop->key()->IsPropertyName()) { 6879 if (!prop->key()->IsPropertyName()) {
6965 // Keyed function call. 6880 // Keyed function call.
6966 CHECK_ALIVE(VisitArgument(prop->obj())); 6881 CHECK_ALIVE(VisitArgument(prop->obj()));
6967 6882
6968 CHECK_ALIVE(VisitForValue(prop->key())); 6883 CHECK_ALIVE(VisitForValue(prop->key()));
6969 // Push receiver and key like the non-optimized code generator expects it. 6884 // Push receiver and key like the non-optimized code generator expects it.
6970 HValue* key = Pop(); 6885 HValue* key = Pop();
6971 HValue* receiver = Pop(); 6886 HValue* receiver = Pop();
6972 Push(key); 6887 Push(key);
6973 Push(receiver); 6888 Push(receiver);
6974 6889
6975 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 6890 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
6976 6891
6977 HValue* context = environment()->LookupContext(); 6892 HValue* context = environment()->context();
6978 call = new(zone()) HCallKeyed(context, key, argument_count); 6893 call = new(zone()) HCallKeyed(context, key, argument_count);
6979 call->set_position(expr->position()); 6894 call->set_position(expr->position());
6980 Drop(argument_count + 1); // 1 is the key. 6895 Drop(argument_count + 1); // 1 is the key.
6981 return ast_context()->ReturnInstruction(call, expr->id()); 6896 return ast_context()->ReturnInstruction(call, expr->id());
6982 } 6897 }
6983 6898
6984 // Named function call. 6899 // Named function call.
6985 if (TryCallApply(expr)) return; 6900 if (TryCallApply(expr)) return;
6986 6901
6987 CHECK_ALIVE(VisitForValue(prop->obj())); 6902 CHECK_ALIVE(VisitForValue(prop->obj()));
6988 CHECK_ALIVE(VisitExpressions(expr->arguments())); 6903 CHECK_ALIVE(VisitExpressions(expr->arguments()));
6989 6904
6990 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 6905 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
6991 SmallMapList* types = expr->GetReceiverTypes(); 6906 SmallMapList* types = expr->GetReceiverTypes();
6992 6907
6993 bool monomorphic = expr->IsMonomorphic(); 6908 bool monomorphic = expr->IsMonomorphic();
6994 Handle<Map> receiver_map; 6909 Handle<Map> receiver_map;
6995 if (monomorphic) { 6910 if (monomorphic) {
6996 receiver_map = (types == NULL || types->is_empty()) 6911 receiver_map = (types == NULL || types->is_empty())
6997 ? Handle<Map>::null() 6912 ? Handle<Map>::null()
6998 : types->first(); 6913 : types->first();
6999 } else {
7000 Map* family_map = CheckSameElementsFamily(types);
7001 if (family_map != NULL) {
7002 receiver_map = Handle<Map>(family_map);
7003 monomorphic = expr->ComputeTarget(receiver_map, name);
7004 }
7005 } 6914 }
7006 6915
7007 HValue* receiver = 6916 HValue* receiver =
7008 environment()->ExpressionStackAt(expr->arguments()->length()); 6917 environment()->ExpressionStackAt(expr->arguments()->length());
7009 if (monomorphic) { 6918 if (monomorphic) {
7010 if (TryInlineBuiltinMethodCall(expr, 6919 if (TryInlineBuiltinMethodCall(expr,
7011 receiver, 6920 receiver,
7012 receiver_map, 6921 receiver_map,
7013 expr->check_type())) { 6922 expr->check_type())) {
7014 if (FLAG_trace_inlining) { 6923 if (FLAG_trace_inlining) {
7015 PrintF("Inlining builtin "); 6924 PrintF("Inlining builtin ");
7016 expr->target()->ShortPrint(); 6925 expr->target()->ShortPrint();
7017 PrintF("\n"); 6926 PrintF("\n");
7018 } 6927 }
7019 return; 6928 return;
7020 } 6929 }
7021 6930
7022 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 6931 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) ||
7023 expr->check_type() != RECEIVER_MAP_CHECK) { 6932 expr->check_type() != RECEIVER_MAP_CHECK) {
7024 // When the target has a custom call IC generator, use the IC, 6933 // When the target has a custom call IC generator, use the IC,
7025 // because it is likely to generate better code. Also use the IC 6934 // because it is likely to generate better code. Also use the IC
7026 // when a primitive receiver check is required. 6935 // when a primitive receiver check is required.
7027 HValue* context = environment()->LookupContext(); 6936 HValue* context = environment()->context();
7028 call = PreProcessCall( 6937 call = PreProcessCall(
7029 new(zone()) HCallNamed(context, name, argument_count)); 6938 new(zone()) HCallNamed(context, name, argument_count));
7030 } else { 6939 } else {
7031 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6940 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7032 6941
7033 if (TryInlineCall(expr)) return; 6942 if (TryInlineCall(expr)) return;
7034 call = PreProcessCall( 6943 call = PreProcessCall(
7035 new(zone()) HCallConstantFunction(expr->target(), 6944 new(zone()) HCallConstantFunction(expr->target(),
7036 argument_count)); 6945 argument_count));
7037 } 6946 }
7038 } else if (types != NULL && types->length() > 1) { 6947 } else if (types != NULL && types->length() > 1) {
7039 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 6948 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
7040 HandlePolymorphicCallNamed(expr, receiver, types, name); 6949 HandlePolymorphicCallNamed(expr, receiver, types, name);
7041 return; 6950 return;
7042 6951
7043 } else { 6952 } else {
7044 HValue* context = environment()->LookupContext(); 6953 HValue* context = environment()->context();
7045 call = PreProcessCall( 6954 call = PreProcessCall(
7046 new(zone()) HCallNamed(context, name, argument_count)); 6955 new(zone()) HCallNamed(context, name, argument_count));
7047 } 6956 }
7048 6957
7049 } else { 6958 } else {
7050 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 6959 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7051 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { 6960 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
7052 return Bailout("possible direct call to eval"); 6961 return Bailout(kPossibleDirectCallToEval);
7053 } 6962 }
7054 6963
7055 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 6964 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
7056 if (global_call) { 6965 if (global_call) {
7057 Variable* var = proxy->var(); 6966 Variable* var = proxy->var();
7058 bool known_global_function = false; 6967 bool known_global_function = false;
7059 // If there is a global property cell for the name at compile time and 6968 // If there is a global property cell for the name at compile time and
7060 // access check is not enabled we assume that the function will not change 6969 // access check is not enabled we assume that the function will not change
7061 // and generate optimized code for calling the function. 6970 // and generate optimized code for calling the function.
7062 LookupResult lookup(isolate()); 6971 LookupResult lookup(isolate());
7063 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 6972 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
7064 if (type == kUseCell && 6973 if (type == kUseCell &&
7065 !current_info()->global_object()->IsAccessCheckNeeded()) { 6974 !current_info()->global_object()->IsAccessCheckNeeded()) {
7066 Handle<GlobalObject> global(current_info()->global_object()); 6975 Handle<GlobalObject> global(current_info()->global_object());
7067 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 6976 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
7068 } 6977 }
7069 if (known_global_function) { 6978 if (known_global_function) {
7070 // Push the global object instead of the global receiver because 6979 // Push the global object instead of the global receiver because
7071 // code generated by the full code generator expects it. 6980 // code generated by the full code generator expects it.
7072 HValue* context = environment()->LookupContext(); 6981 HValue* context = environment()->context();
7073 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 6982 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
7074 PushAndAdd(global_object); 6983 PushAndAdd(global_object);
7075 CHECK_ALIVE(VisitExpressions(expr->arguments())); 6984 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7076 6985
7077 CHECK_ALIVE(VisitForValue(expr->expression())); 6986 CHECK_ALIVE(VisitForValue(expr->expression()));
7078 HValue* function = Pop(); 6987 HValue* function = Pop();
7079 Add<HCheckFunction>(function, expr->target()); 6988 Add<HCheckFunction>(function, expr->target());
7080 6989
7081 // Replace the global object with the global receiver. 6990 // Replace the global object with the global receiver.
7082 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object); 6991 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object);
(...skipping 13 matching lines...) Expand all
7096 } 7005 }
7097 if (TryInlineCall(expr)) return; 7006 if (TryInlineCall(expr)) return;
7098 7007
7099 if (expr->target().is_identical_to(current_info()->closure())) { 7008 if (expr->target().is_identical_to(current_info()->closure())) {
7100 graph()->MarkRecursive(); 7009 graph()->MarkRecursive();
7101 } 7010 }
7102 7011
7103 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { 7012 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
7104 // When the target has a custom call IC generator, use the IC, 7013 // When the target has a custom call IC generator, use the IC,
7105 // because it is likely to generate better code. 7014 // because it is likely to generate better code.
7106 HValue* context = environment()->LookupContext(); 7015 HValue* context = environment()->context();
7107 call = PreProcessCall( 7016 call = PreProcessCall(
7108 new(zone()) HCallNamed(context, var->name(), argument_count)); 7017 new(zone()) HCallNamed(context, var->name(), argument_count));
7109 } else { 7018 } else {
7110 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 7019 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
7111 argument_count)); 7020 argument_count));
7112 } 7021 }
7113 } else { 7022 } else {
7114 HValue* context = environment()->LookupContext(); 7023 HGlobalObject* receiver = Add<HGlobalObject>();
7115 HGlobalObject* receiver = Add<HGlobalObject>(context); 7024 PushAndAdd(New<HPushArgument>(receiver));
7116 PushAndAdd(new(zone()) HPushArgument(receiver));
7117 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7025 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7118 7026
7119 call = new(zone()) HCallGlobal(context, var->name(), argument_count); 7027 call = New<HCallGlobal>(var->name(), argument_count);
7120 Drop(argument_count); 7028 Drop(argument_count);
7121 } 7029 }
7122 7030
7123 } else if (expr->IsMonomorphic()) { 7031 } else if (expr->IsMonomorphic()) {
7124 // The function is on the stack in the unoptimized code during 7032 // The function is on the stack in the unoptimized code during
7125 // evaluation of the arguments. 7033 // evaluation of the arguments.
7126 CHECK_ALIVE(VisitForValue(expr->expression())); 7034 CHECK_ALIVE(VisitForValue(expr->expression()));
7127 HValue* function = Top(); 7035 HValue* function = Top();
7128 HValue* context = environment()->LookupContext(); 7036 HGlobalObject* global = Add<HGlobalObject>();
7129 HGlobalObject* global = Add<HGlobalObject>(context); 7037 HGlobalReceiver* receiver = New<HGlobalReceiver>(global);
7130 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
7131 PushAndAdd(receiver); 7038 PushAndAdd(receiver);
7132 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7039 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7133 Add<HCheckFunction>(function, expr->target()); 7040 Add<HCheckFunction>(function, expr->target());
7134 7041
7135 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 7042 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function.
7136 if (FLAG_trace_inlining) { 7043 if (FLAG_trace_inlining) {
7137 PrintF("Inlining builtin "); 7044 PrintF("Inlining builtin ");
7138 expr->target()->ShortPrint(); 7045 expr->target()->ShortPrint();
7139 PrintF("\n"); 7046 PrintF("\n");
7140 } 7047 }
7141 return; 7048 return;
7142 } 7049 }
7143 7050
7144 if (TryInlineCall(expr, true)) { // Drop function from environment. 7051 if (TryInlineCall(expr, true)) { // Drop function from environment.
7145 return; 7052 return;
7146 } else { 7053 } else {
7147 call = PreProcessCall( 7054 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(),
7148 new(zone()) HInvokeFunction(context, 7055 argument_count));
7149 function,
7150 expr->target(),
7151 argument_count));
7152 Drop(1); // The function. 7056 Drop(1); // The function.
7153 } 7057 }
7154 7058
7155 } else { 7059 } else {
7156 CHECK_ALIVE(VisitForValue(expr->expression())); 7060 CHECK_ALIVE(VisitForValue(expr->expression()));
7157 HValue* function = Top(); 7061 HValue* function = Top();
7158 HValue* context = environment()->LookupContext(); 7062 HGlobalObject* global_object = Add<HGlobalObject>();
7159 HGlobalObject* global_object = Add<HGlobalObject>(context);
7160 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); 7063 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object);
7161 PushAndAdd(new(zone()) HPushArgument(receiver)); 7064 PushAndAdd(New<HPushArgument>(receiver));
7162 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7065 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7163 7066
7164 call = new(zone()) HCallFunction(context, function, argument_count); 7067 call = New<HCallFunction>(function, argument_count);
7165 Drop(argument_count + 1); 7068 Drop(argument_count + 1);
7166 } 7069 }
7167 } 7070 }
7168 7071
7169 call->set_position(expr->position()); 7072 call->set_position(expr->position());
7170 return ast_context()->ReturnInstruction(call, expr->id()); 7073 return ast_context()->ReturnInstruction(call, expr->id());
7171 } 7074 }
7172 7075
7173 7076
7174 // Checks whether allocation using the given constructor can be inlined. 7077 // Checks whether allocation using the given constructor can be inlined.
7175 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 7078 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7176 return constructor->has_initial_map() && 7079 return constructor->has_initial_map() &&
7177 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 7080 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
7178 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && 7081 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
7179 constructor->initial_map()->InitialPropertiesLength() == 0; 7082 constructor->initial_map()->InitialPropertiesLength() == 0;
7180 } 7083 }
7181 7084
7182 7085
7183 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 7086 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
7184 ASSERT(!HasStackOverflow()); 7087 ASSERT(!HasStackOverflow());
7185 ASSERT(current_block() != NULL); 7088 ASSERT(current_block() != NULL);
7186 ASSERT(current_block()->HasPredecessor()); 7089 ASSERT(current_block()->HasPredecessor());
7187 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 7090 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
7188 HValue* context = environment()->LookupContext(); 7091 HValue* context = environment()->context();
7189 Factory* factory = isolate()->factory(); 7092 Factory* factory = isolate()->factory();
7190 7093
7191 if (FLAG_inline_construct && 7094 if (FLAG_inline_construct &&
7192 expr->IsMonomorphic() && 7095 expr->IsMonomorphic() &&
7193 IsAllocationInlineable(expr->target())) { 7096 IsAllocationInlineable(expr->target())) {
7194 // The constructor function is on the stack in the unoptimized code 7097 // The constructor function is on the stack in the unoptimized code
7195 // during evaluation of the arguments. 7098 // during evaluation of the arguments.
7196 CHECK_ALIVE(VisitForValue(expr->expression())); 7099 CHECK_ALIVE(VisitForValue(expr->expression()));
7197 HValue* function = Top(); 7100 HValue* function = Top();
7198 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7101 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7199 Handle<JSFunction> constructor = expr->target(); 7102 Handle<JSFunction> constructor = expr->target();
7200 HValue* check = Add<HCheckFunction>(function, constructor); 7103 HValue* check = Add<HCheckFunction>(function, constructor);
7201 7104
7202 // Force completion of inobject slack tracking before generating 7105 // Force completion of inobject slack tracking before generating
7203 // allocation code to finalize instance size. 7106 // allocation code to finalize instance size.
7204 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 7107 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
7205 constructor->shared()->CompleteInobjectSlackTracking(); 7108 constructor->shared()->CompleteInobjectSlackTracking();
7206 } 7109 }
7207 7110
7208 // Calculate instance size from initial map of constructor. 7111 // Calculate instance size from initial map of constructor.
7209 ASSERT(constructor->has_initial_map()); 7112 ASSERT(constructor->has_initial_map());
7210 Handle<Map> initial_map(constructor->initial_map()); 7113 Handle<Map> initial_map(constructor->initial_map());
7211 int instance_size = initial_map->instance_size(); 7114 int instance_size = initial_map->instance_size();
7212 ASSERT(initial_map->InitialPropertiesLength() == 0); 7115 ASSERT(initial_map->InitialPropertiesLength() == 0);
7213 7116
7214 // Allocate an instance of the implicit receiver object. 7117 // Allocate an instance of the implicit receiver object.
7215 HValue* size_in_bytes = Add<HConstant>(instance_size); 7118 HValue* size_in_bytes = Add<HConstant>(instance_size);
7216 HAllocate::Flags flags = HAllocate::DefaultFlags(); 7119 PretenureFlag pretenure_flag =
7217 if (FLAG_pretenuring_call_new && 7120 (FLAG_pretenuring_call_new &&
7218 isolate()->heap()->ShouldGloballyPretenure()) { 7121 isolate()->heap()->GetPretenureMode() == TENURED)
7219 flags = static_cast<HAllocate::Flags>( 7122 ? TENURED : NOT_TENURED;
7220 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
7221 }
7222 HAllocate* receiver = 7123 HAllocate* receiver =
7223 Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); 7124 Add<HAllocate>(size_in_bytes, HType::JSObject(), pretenure_flag,
7125 JS_OBJECT_TYPE);
7224 receiver->set_known_initial_map(initial_map); 7126 receiver->set_known_initial_map(initial_map);
7225 7127
7226 // Load the initial map from the constructor. 7128 // Load the initial map from the constructor.
7227 HValue* constructor_value = Add<HConstant>(constructor); 7129 HValue* constructor_value = Add<HConstant>(constructor);
7228 HValue* initial_map_value = 7130 HValue* initial_map_value =
7229 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( 7131 Add<HLoadNamedField>(constructor_value, HObjectAccess::ForJSObjectOffset(
7230 JSFunction::kPrototypeOrInitialMapOffset)); 7132 JSFunction::kPrototypeOrInitialMapOffset));
7231 7133
7232 // Initialize map and fields of the newly allocated object. 7134 // Initialize map and fields of the newly allocated object.
7233 { NoObservableSideEffectsScope no_effects(this); 7135 { NoObservableSideEffectsScope no_effects(this);
7234 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); 7136 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
7235 AddStore(receiver, 7137 Add<HStoreNamedField>(receiver,
7236 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), 7138 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset),
7237 initial_map_value); 7139 initial_map_value);
7238 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); 7140 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
7239 AddStore(receiver, 7141 Add<HStoreNamedField>(receiver,
7240 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), 7142 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset),
7241 empty_fixed_array); 7143 empty_fixed_array);
7242 AddStore(receiver, 7144 Add<HStoreNamedField>(receiver,
7243 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), 7145 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset),
7244 empty_fixed_array); 7146 empty_fixed_array);
7245 if (initial_map->inobject_properties() != 0) { 7147 if (initial_map->inobject_properties() != 0) {
7246 HConstant* undefined = graph()->GetConstantUndefined(); 7148 HConstant* undefined = graph()->GetConstantUndefined();
7247 for (int i = 0; i < initial_map->inobject_properties(); i++) { 7149 for (int i = 0; i < initial_map->inobject_properties(); i++) {
7248 int property_offset = JSObject::kHeaderSize + i * kPointerSize; 7150 int property_offset = JSObject::kHeaderSize + i * kPointerSize;
7249 AddStore(receiver, 7151 Add<HStoreNamedField>(receiver,
7250 HObjectAccess::ForJSObjectOffset(property_offset), 7152 HObjectAccess::ForJSObjectOffset(property_offset),
7251 undefined); 7153 undefined);
7252 } 7154 }
7253 } 7155 }
7254 } 7156 }
7255 7157
7256 // Replace the constructor function with a newly allocated receiver using 7158 // Replace the constructor function with a newly allocated receiver using
7257 // the index of the receiver from the top of the expression stack. 7159 // the index of the receiver from the top of the expression stack.
7258 const int receiver_index = argument_count - 1; 7160 const int receiver_index = argument_count - 1;
7259 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); 7161 ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
7260 environment()->SetExpressionStackAt(receiver_index, receiver); 7162 environment()->SetExpressionStackAt(receiver_index, receiver);
7261 7163
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
7317 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 7219 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
7318 }; 7220 };
7319 #undef INLINE_FUNCTION_GENERATOR_ADDRESS 7221 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
7320 7222
7321 7223
7322 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 7224 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
7323 ASSERT(!HasStackOverflow()); 7225 ASSERT(!HasStackOverflow());
7324 ASSERT(current_block() != NULL); 7226 ASSERT(current_block() != NULL);
7325 ASSERT(current_block()->HasPredecessor()); 7227 ASSERT(current_block()->HasPredecessor());
7326 if (expr->is_jsruntime()) { 7228 if (expr->is_jsruntime()) {
7327 return Bailout("call to a JavaScript runtime function"); 7229 return Bailout(kCallToAJavaScriptRuntimeFunction);
7328 } 7230 }
7329 7231
7330 const Runtime::Function* function = expr->function(); 7232 const Runtime::Function* function = expr->function();
7331 ASSERT(function != NULL); 7233 ASSERT(function != NULL);
7332 if (function->intrinsic_type == Runtime::INLINE) { 7234 if (function->intrinsic_type == Runtime::INLINE) {
7333 ASSERT(expr->name()->length() > 0); 7235 ASSERT(expr->name()->length() > 0);
7334 ASSERT(expr->name()->Get(0) == '_'); 7236 ASSERT(expr->name()->Get(0) == '_');
7335 // Call to an inline function. 7237 // Call to an inline function.
7336 int lookup_index = static_cast<int>(function->function_id) - 7238 int lookup_index = static_cast<int>(function->function_id) -
7337 static_cast<int>(Runtime::kFirstInlineFunction); 7239 static_cast<int>(Runtime::kFirstInlineFunction);
7338 ASSERT(lookup_index >= 0); 7240 ASSERT(lookup_index >= 0);
7339 ASSERT(static_cast<size_t>(lookup_index) < 7241 ASSERT(static_cast<size_t>(lookup_index) <
7340 ARRAY_SIZE(kInlineFunctionGenerators)); 7242 ARRAY_SIZE(kInlineFunctionGenerators));
7341 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 7243 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
7342 7244
7343 // Call the inline code generator using the pointer-to-member. 7245 // Call the inline code generator using the pointer-to-member.
7344 (this->*generator)(expr); 7246 (this->*generator)(expr);
7345 } else { 7247 } else {
7346 ASSERT(function->intrinsic_type == Runtime::RUNTIME); 7248 ASSERT(function->intrinsic_type == Runtime::RUNTIME);
7347 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7249 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7348 7250
7349 HValue* context = environment()->LookupContext();
7350 Handle<String> name = expr->name(); 7251 Handle<String> name = expr->name();
7351 int argument_count = expr->arguments()->length(); 7252 int argument_count = expr->arguments()->length();
7352 HCallRuntime* call = 7253 HCallRuntime* call = New<HCallRuntime>(name, function,
7353 new(zone()) HCallRuntime(context, name, function, argument_count); 7254 argument_count);
7354 Drop(argument_count); 7255 Drop(argument_count);
7355 return ast_context()->ReturnInstruction(call, expr->id()); 7256 return ast_context()->ReturnInstruction(call, expr->id());
7356 } 7257 }
7357 } 7258 }
7358 7259
7359 7260
7360 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 7261 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
7361 ASSERT(!HasStackOverflow()); 7262 ASSERT(!HasStackOverflow());
7362 ASSERT(current_block() != NULL); 7263 ASSERT(current_block() != NULL);
7363 ASSERT(current_block()->HasPredecessor()); 7264 ASSERT(current_block()->HasPredecessor());
(...skipping 10 matching lines...) Expand all
7374 7275
7375 7276
7376 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { 7277 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
7377 Property* prop = expr->expression()->AsProperty(); 7278 Property* prop = expr->expression()->AsProperty();
7378 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 7279 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7379 if (prop != NULL) { 7280 if (prop != NULL) {
7380 CHECK_ALIVE(VisitForValue(prop->obj())); 7281 CHECK_ALIVE(VisitForValue(prop->obj()));
7381 CHECK_ALIVE(VisitForValue(prop->key())); 7282 CHECK_ALIVE(VisitForValue(prop->key()));
7382 HValue* key = Pop(); 7283 HValue* key = Pop();
7383 HValue* obj = Pop(); 7284 HValue* obj = Pop();
7384 HValue* context = environment()->LookupContext(); 7285 HValue* function = AddLoadJSBuiltin(Builtins::DELETE);
7385 HValue* function = AddLoadJSBuiltin(Builtins::DELETE, context);
7386 Add<HPushArgument>(obj); 7286 Add<HPushArgument>(obj);
7387 Add<HPushArgument>(key); 7287 Add<HPushArgument>(key);
7388 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); 7288 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag()));
7389 // TODO(olivf) InvokeFunction produces a check for the parameter count, 7289 // TODO(olivf) InvokeFunction produces a check for the parameter count,
7390 // even though we are certain to pass the correct number of arguments here. 7290 // even though we are certain to pass the correct number of arguments here.
7391 HInstruction* instr = new(zone()) HInvokeFunction(context, function, 3); 7291 HInstruction* instr = New<HInvokeFunction>(function, 3);
7392 return ast_context()->ReturnInstruction(instr, expr->id()); 7292 return ast_context()->ReturnInstruction(instr, expr->id());
7393 } else if (proxy != NULL) { 7293 } else if (proxy != NULL) {
7394 Variable* var = proxy->var(); 7294 Variable* var = proxy->var();
7395 if (var->IsUnallocated()) { 7295 if (var->IsUnallocated()) {
7396 Bailout("delete with global variable"); 7296 Bailout(kDeleteWithGlobalVariable);
7397 } else if (var->IsStackAllocated() || var->IsContextSlot()) { 7297 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
7398 // Result of deleting non-global variables is false. 'this' is not 7298 // Result of deleting non-global variables is false. 'this' is not
7399 // really a variable, though we implement it as one. The 7299 // really a variable, though we implement it as one. The
7400 // subexpression does not have side effects. 7300 // subexpression does not have side effects.
7401 HValue* value = var->is_this() 7301 HValue* value = var->is_this()
7402 ? graph()->GetConstantTrue() 7302 ? graph()->GetConstantTrue()
7403 : graph()->GetConstantFalse(); 7303 : graph()->GetConstantFalse();
7404 return ast_context()->ReturnValue(value); 7304 return ast_context()->ReturnValue(value);
7405 } else { 7305 } else {
7406 Bailout("delete with non-global variable"); 7306 Bailout(kDeleteWithNonGlobalVariable);
7407 } 7307 }
7408 } else { 7308 } else {
7409 // Result of deleting non-property, non-variable reference is true. 7309 // Result of deleting non-property, non-variable reference is true.
7410 // Evaluate the subexpression for side effects. 7310 // Evaluate the subexpression for side effects.
7411 CHECK_ALIVE(VisitForEffect(expr->expression())); 7311 CHECK_ALIVE(VisitForEffect(expr->expression()));
7412 return ast_context()->ReturnValue(graph()->GetConstantTrue()); 7312 return ast_context()->ReturnValue(graph()->GetConstantTrue());
7413 } 7313 }
7414 } 7314 }
7415 7315
7416 7316
7417 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { 7317 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
7418 CHECK_ALIVE(VisitForEffect(expr->expression())); 7318 CHECK_ALIVE(VisitForEffect(expr->expression()));
7419 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 7319 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
7420 } 7320 }
7421 7321
7422 7322
7423 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { 7323 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
7424 CHECK_ALIVE(VisitForTypeOf(expr->expression())); 7324 CHECK_ALIVE(VisitForTypeOf(expr->expression()));
7425 HValue* value = Pop(); 7325 HValue* value = Pop();
7426 HValue* context = environment()->LookupContext(); 7326 HValue* context = environment()->context();
7427 HInstruction* instr = new(zone()) HTypeof(context, value); 7327 HInstruction* instr = new(zone()) HTypeof(context, value);
7428 return ast_context()->ReturnInstruction(instr, expr->id()); 7328 return ast_context()->ReturnInstruction(instr, expr->id());
7429 } 7329 }
7430 7330
7431 7331
7432 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { 7332 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
7433 CHECK_ALIVE(VisitForValue(expr->expression())); 7333 CHECK_ALIVE(VisitForValue(expr->expression()));
7434 Handle<Type> operand_type = expr->expression()->bounds().lower; 7334 Handle<Type> operand_type = expr->expression()->bounds().lower;
7435 HValue* value = TruncateToNumber(Pop(), &operand_type); 7335 HValue* value = TruncateToNumber(Pop(), &operand_type);
7436 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); 7336 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
7513 } 7413 }
7514 Push(number_input); 7414 Push(number_input);
7515 } 7415 }
7516 7416
7517 // The addition has no side effects, so we do not need 7417 // The addition has no side effects, so we do not need
7518 // to simulate the expression stack after this instruction. 7418 // to simulate the expression stack after this instruction.
7519 // Any later failures deopt to the load of the input or earlier. 7419 // Any later failures deopt to the load of the input or earlier.
7520 HConstant* delta = (expr->op() == Token::INC) 7420 HConstant* delta = (expr->op() == Token::INC)
7521 ? graph()->GetConstant1() 7421 ? graph()->GetConstant1()
7522 : graph()->GetConstantMinus1(); 7422 : graph()->GetConstantMinus1();
7523 HValue* context = environment()->LookupContext(); 7423 HInstruction* instr = Add<HAdd>(Top(), delta);
7524 HInstruction* instr = HAdd::New(zone(), context, Top(), delta);
7525 instr->SetFlag(HInstruction::kCannotBeTagged); 7424 instr->SetFlag(HInstruction::kCannotBeTagged);
7526 instr->ClearAllSideEffects(); 7425 instr->ClearAllSideEffects();
7527 AddInstruction(instr);
7528 return instr; 7426 return instr;
7529 } 7427 }
7530 7428
7531 7429
7532 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { 7430 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
7533 ASSERT(!HasStackOverflow()); 7431 ASSERT(!HasStackOverflow());
7534 ASSERT(current_block() != NULL); 7432 ASSERT(current_block() != NULL);
7535 ASSERT(current_block()->HasPredecessor()); 7433 ASSERT(current_block()->HasPredecessor());
7536 Expression* target = expr->expression(); 7434 Expression* target = expr->expression();
7537 VariableProxy* proxy = target->AsVariableProxy(); 7435 VariableProxy* proxy = target->AsVariableProxy();
7538 Property* prop = target->AsProperty(); 7436 Property* prop = target->AsProperty();
7539 if (proxy == NULL && prop == NULL) { 7437 if (proxy == NULL && prop == NULL) {
7540 return Bailout("invalid lhs in count operation"); 7438 return Bailout(kInvalidLhsInCountOperation);
7541 } 7439 }
7542 7440
7543 // Match the full code generator stack by simulating an extra stack 7441 // Match the full code generator stack by simulating an extra stack
7544 // element for postfix operations in a non-effect context. The return 7442 // element for postfix operations in a non-effect context. The return
7545 // value is ToNumber(input). 7443 // value is ToNumber(input).
7546 bool returns_original_input = 7444 bool returns_original_input =
7547 expr->is_postfix() && !ast_context()->IsEffect(); 7445 expr->is_postfix() && !ast_context()->IsEffect();
7548 HValue* input = NULL; // ToNumber(original_input). 7446 HValue* input = NULL; // ToNumber(original_input).
7549 HValue* after = NULL; // The result after incrementing or decrementing. 7447 HValue* after = NULL; // The result after incrementing or decrementing.
7550 7448
7551 if (proxy != NULL) { 7449 if (proxy != NULL) {
7552 Variable* var = proxy->var(); 7450 Variable* var = proxy->var();
7553 if (var->mode() == CONST) { 7451 if (var->mode() == CONST) {
7554 return Bailout("unsupported count operation with const"); 7452 return Bailout(kUnsupportedCountOperationWithConst);
7555 } 7453 }
7556 // Argument of the count operation is a variable, not a property. 7454 // Argument of the count operation is a variable, not a property.
7557 ASSERT(prop == NULL); 7455 ASSERT(prop == NULL);
7558 CHECK_ALIVE(VisitForValue(target)); 7456 CHECK_ALIVE(VisitForValue(target));
7559 7457
7560 after = BuildIncrement(returns_original_input, expr); 7458 after = BuildIncrement(returns_original_input, expr);
7561 input = returns_original_input ? Top() : Pop(); 7459 input = returns_original_input ? Top() : Pop();
7562 Push(after); 7460 Push(after);
7563 7461
7564 switch (var->location()) { 7462 switch (var->location()) {
(...skipping 13 matching lines...) Expand all
7578 // Bail out if we try to mutate a parameter value in a function 7476 // Bail out if we try to mutate a parameter value in a function
7579 // using the arguments object. We do not (yet) correctly handle the 7477 // using the arguments object. We do not (yet) correctly handle the
7580 // arguments property of the function. 7478 // arguments property of the function.
7581 if (current_info()->scope()->arguments() != NULL) { 7479 if (current_info()->scope()->arguments() != NULL) {
7582 // Parameters will rewrite to context slots. We have no direct 7480 // Parameters will rewrite to context slots. We have no direct
7583 // way to detect that the variable is a parameter so we use a 7481 // way to detect that the variable is a parameter so we use a
7584 // linear search of the parameter list. 7482 // linear search of the parameter list.
7585 int count = current_info()->scope()->num_parameters(); 7483 int count = current_info()->scope()->num_parameters();
7586 for (int i = 0; i < count; ++i) { 7484 for (int i = 0; i < count; ++i) {
7587 if (var == current_info()->scope()->parameter(i)) { 7485 if (var == current_info()->scope()->parameter(i)) {
7588 return Bailout("assignment to parameter in arguments object"); 7486 return Bailout(kAssignmentToParameterInArgumentsObject);
7589 } 7487 }
7590 } 7488 }
7591 } 7489 }
7592 7490
7593 HValue* context = BuildContextChainWalk(var); 7491 HValue* context = BuildContextChainWalk(var);
7594 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) 7492 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
7595 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; 7493 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
7596 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), 7494 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
7597 mode, after); 7495 mode, after);
7598 if (instr->HasObservableSideEffects()) { 7496 if (instr->HasObservableSideEffects()) {
7599 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); 7497 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
7600 } 7498 }
7601 break; 7499 break;
7602 } 7500 }
7603 7501
7604 case Variable::LOOKUP: 7502 case Variable::LOOKUP:
7605 return Bailout("lookup variable in count operation"); 7503 return Bailout(kLookupVariableInCountOperation);
7606 } 7504 }
7607 7505
7608 } else { 7506 } else {
7609 // Argument of the count operation is a property. 7507 // Argument of the count operation is a property.
7610 ASSERT(prop != NULL); 7508 ASSERT(prop != NULL);
7611 7509
7612 if (prop->key()->IsPropertyName()) { 7510 if (prop->key()->IsPropertyName()) {
7613 // Named property. 7511 // Named property.
7614 if (returns_original_input) Push(graph()->GetConstantUndefined()); 7512 if (returns_original_input) Push(graph()->GetConstantUndefined());
7615 7513
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
7682 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); 7580 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
7683 } 7581 }
7684 } 7582 }
7685 7583
7686 Drop(returns_original_input ? 2 : 1); 7584 Drop(returns_original_input ? 2 : 1);
7687 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); 7585 return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
7688 } 7586 }
7689 7587
7690 7588
7691 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( 7589 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
7692 HValue* context,
7693 HValue* string, 7590 HValue* string,
7694 HValue* index) { 7591 HValue* index) {
7695 if (string->IsConstant() && index->IsConstant()) { 7592 if (string->IsConstant() && index->IsConstant()) {
7696 HConstant* c_string = HConstant::cast(string); 7593 HConstant* c_string = HConstant::cast(string);
7697 HConstant* c_index = HConstant::cast(index); 7594 HConstant* c_index = HConstant::cast(index);
7698 if (c_string->HasStringValue() && c_index->HasNumberValue()) { 7595 if (c_string->HasStringValue() && c_index->HasNumberValue()) {
7699 int32_t i = c_index->NumberValueAsInteger32(); 7596 int32_t i = c_index->NumberValueAsInteger32();
7700 Handle<String> s = c_string->StringValue(); 7597 Handle<String> s = c_string->StringValue();
7701 if (i < 0 || i >= s->length()) { 7598 if (i < 0 || i >= s->length()) {
7702 return new(zone()) HConstant(OS::nan_value()); 7599 return New<HConstant>(OS::nan_value());
7703 } 7600 }
7704 return new(zone()) HConstant(s->Get(i)); 7601 return New<HConstant>(s->Get(i));
7705 } 7602 }
7706 } 7603 }
7707 BuildCheckHeapObject(string); 7604 BuildCheckHeapObject(string);
7708 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); 7605 HValue* checkstring =
7709 HInstruction* length = HStringLength::New(zone(), string); 7606 AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
7607 HInstruction* length = BuildLoadStringLength(string, checkstring);
7710 AddInstruction(length); 7608 AddInstruction(length);
7711 HInstruction* checked_index = Add<HBoundsCheck>(index, length); 7609 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
7712 return new(zone()) HStringCharCodeAt(context, string, checked_index); 7610 return New<HStringCharCodeAt>(string, checked_index);
7713 } 7611 }
7714 7612
7715 7613
7716 // Checks if the given shift amounts have form: (sa) and (32 - sa). 7614 // Checks if the given shift amounts have form: (sa) and (32 - sa).
7717 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, 7615 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
7718 HValue* const32_minus_sa) { 7616 HValue* const32_minus_sa) {
7719 if (!const32_minus_sa->IsSub()) return false; 7617 if (!const32_minus_sa->IsSub()) return false;
7720 HSub* sub = HSub::cast(const32_minus_sa); 7618 HSub* sub = HSub::cast(const32_minus_sa);
7721 if (sa != sub->right()) return false; 7619 if (sa != sub->right()) return false;
7722 HValue* const32 = sub->left(); 7620 HValue* const32 = sub->left();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
7772 7670
7773 7671
7774 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { 7672 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) {
7775 if (value->IsConstant()) { 7673 if (value->IsConstant()) {
7776 HConstant* constant = HConstant::cast(value); 7674 HConstant* constant = HConstant::cast(value);
7777 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); 7675 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
7778 if (number.has_value) { 7676 if (number.has_value) {
7779 *expected = handle(Type::Number(), isolate()); 7677 *expected = handle(Type::Number(), isolate());
7780 return AddInstruction(number.value); 7678 return AddInstruction(number.value);
7781 } 7679 }
7782 return value;
7783 }
7784
7785 Handle<Type> expected_type = *expected;
7786 Representation rep = Representation::FromType(expected_type);
7787 if (!rep.IsTagged()) return value;
7788
7789 // If our type feedback suggests that we can non-observably truncate to number
7790 // we introduce the appropriate check here. This avoids 'value' having a
7791 // tagged representation later on.
7792 if (expected_type->Is(Type::Oddball())) {
7793 // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to
7794 // also record booleans and convert them to 0/1 here.
7795 IfBuilder if_nan(this);
7796 if_nan.If<HCompareObjectEqAndBranch>(value,
7797 graph()->GetConstantUndefined());
7798 if_nan.Then();
7799 if_nan.ElseDeopt();
7800 if_nan.End();
7801 return Add<HConstant>(OS::nan_value(), Representation::Double());
7802 } 7680 }
7803 7681
7804 return value; 7682 return value;
7805 } 7683 }
7806 7684
7807 7685
7808 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( 7686 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
7809 BinaryOperation* expr, 7687 BinaryOperation* expr,
7810 HValue* left, 7688 HValue* left,
7811 HValue* right) { 7689 HValue* right) {
7812 HValue* context = environment()->LookupContext(); 7690 HValue* context = environment()->context();
7813 Handle<Type> left_type = expr->left()->bounds().lower; 7691 Handle<Type> left_type = expr->left()->bounds().lower;
7814 Handle<Type> right_type = expr->right()->bounds().lower; 7692 Handle<Type> right_type = expr->right()->bounds().lower;
7815 Handle<Type> result_type = expr->bounds().lower; 7693 Handle<Type> result_type = expr->bounds().lower;
7816 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 7694 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
7817 Representation left_rep = Representation::FromType(left_type); 7695 Representation left_rep = Representation::FromType(left_type);
7818 Representation right_rep = Representation::FromType(right_type); 7696 Representation right_rep = Representation::FromType(right_type);
7819 Representation result_rep = Representation::FromType(result_type); 7697 Representation result_rep = Representation::FromType(result_type);
7820 7698
7821 if (expr->op() != Token::ADD || 7699 if (expr->op() != Token::ADD ||
7822 (left->type().IsNonString() && right->type().IsNonString())) { 7700 (left->type().IsNonString() && right->type().IsNonString())) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
7855 instr = HMul::New(zone(), context, left, right); 7733 instr = HMul::New(zone(), context, left, right);
7856 break; 7734 break;
7857 case Token::MOD: 7735 case Token::MOD:
7858 instr = HMod::New(zone(), context, left, right, fixed_right_arg); 7736 instr = HMod::New(zone(), context, left, right, fixed_right_arg);
7859 break; 7737 break;
7860 case Token::DIV: 7738 case Token::DIV:
7861 instr = HDiv::New(zone(), context, left, right); 7739 instr = HDiv::New(zone(), context, left, right);
7862 break; 7740 break;
7863 case Token::BIT_XOR: 7741 case Token::BIT_XOR:
7864 case Token::BIT_AND: 7742 case Token::BIT_AND:
7865 instr = HBitwise::New(zone(), expr->op(), context, left, right); 7743 instr = NewUncasted<HBitwise>(expr->op(), left, right);
7866 break; 7744 break;
7867 case Token::BIT_OR: { 7745 case Token::BIT_OR: {
7868 HValue* operand, *shift_amount; 7746 HValue* operand, *shift_amount;
7869 if (left_type->Is(Type::Signed32()) && 7747 if (left_type->Is(Type::Signed32()) &&
7870 right_type->Is(Type::Signed32()) && 7748 right_type->Is(Type::Signed32()) &&
7871 MatchRotateRight(left, right, &operand, &shift_amount)) { 7749 MatchRotateRight(left, right, &operand, &shift_amount)) {
7872 instr = new(zone()) HRor(context, operand, shift_amount); 7750 instr = new(zone()) HRor(context, operand, shift_amount);
7873 } else { 7751 } else {
7874 instr = HBitwise::New(zone(), expr->op(), context, left, right); 7752 instr = NewUncasted<HBitwise>(expr->op(), left, right);
7875 } 7753 }
7876 break; 7754 break;
7877 } 7755 }
7878 case Token::SAR: 7756 case Token::SAR:
7879 instr = HSar::New(zone(), context, left, right); 7757 instr = HSar::New(zone(), context, left, right);
7880 break; 7758 break;
7881 case Token::SHR: 7759 case Token::SHR:
7882 instr = HShr::New(zone(), context, left, right); 7760 instr = HShr::New(zone(), context, left, right);
7883 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && 7761 if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
7884 CanBeZero(right)) { 7762 CanBeZero(right)) {
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
8109 Handle<Type> left_type = expr->left()->bounds().lower; 7987 Handle<Type> left_type = expr->left()->bounds().lower;
8110 Handle<Type> right_type = expr->right()->bounds().lower; 7988 Handle<Type> right_type = expr->right()->bounds().lower;
8111 Handle<Type> combined_type = expr->combined_type(); 7989 Handle<Type> combined_type = expr->combined_type();
8112 Representation combined_rep = Representation::FromType(combined_type); 7990 Representation combined_rep = Representation::FromType(combined_type);
8113 Representation left_rep = Representation::FromType(left_type); 7991 Representation left_rep = Representation::FromType(left_type);
8114 Representation right_rep = Representation::FromType(right_type); 7992 Representation right_rep = Representation::FromType(right_type);
8115 7993
8116 CHECK_ALIVE(VisitForValue(expr->left())); 7994 CHECK_ALIVE(VisitForValue(expr->left()));
8117 CHECK_ALIVE(VisitForValue(expr->right())); 7995 CHECK_ALIVE(VisitForValue(expr->right()));
8118 7996
8119 HValue* context = environment()->LookupContext(); 7997 HValue* context = environment()->context();
8120 HValue* right = Pop(); 7998 HValue* right = Pop();
8121 HValue* left = Pop(); 7999 HValue* left = Pop();
8122 Token::Value op = expr->op(); 8000 Token::Value op = expr->op();
8123 8001
8124 if (IsLiteralCompareBool(left, op, right)) { 8002 if (IsLiteralCompareBool(left, op, right)) {
8125 HCompareObjectEqAndBranch* result = 8003 HCompareObjectEqAndBranch* result =
8126 new(zone()) HCompareObjectEqAndBranch(left, right); 8004 New<HCompareObjectEqAndBranch>(left, right);
8127 result->set_position(expr->position()); 8005 result->set_position(expr->position());
8128 return ast_context()->ReturnControl(result, expr->id()); 8006 return ast_context()->ReturnControl(result, expr->id());
8129 } 8007 }
8130 8008
8131 if (op == Token::INSTANCEOF) { 8009 if (op == Token::INSTANCEOF) {
8132 // Check to see if the rhs of the instanceof is a global function not 8010 // Check to see if the rhs of the instanceof is a global function not
8133 // residing in new space. If it is we assume that the function will stay the 8011 // residing in new space. If it is we assume that the function will stay the
8134 // same. 8012 // same.
8135 Handle<JSFunction> target = Handle<JSFunction>::null(); 8013 Handle<JSFunction> target = Handle<JSFunction>::null();
8136 VariableProxy* proxy = expr->right()->AsVariableProxy(); 8014 VariableProxy* proxy = expr->right()->AsVariableProxy();
(...skipping 25 matching lines...) Expand all
8162 Add<HCheckFunction>(right, target); 8040 Add<HCheckFunction>(right, target);
8163 HInstanceOfKnownGlobal* result = 8041 HInstanceOfKnownGlobal* result =
8164 new(zone()) HInstanceOfKnownGlobal(context, left, target); 8042 new(zone()) HInstanceOfKnownGlobal(context, left, target);
8165 result->set_position(expr->position()); 8043 result->set_position(expr->position());
8166 return ast_context()->ReturnInstruction(result, expr->id()); 8044 return ast_context()->ReturnInstruction(result, expr->id());
8167 } 8045 }
8168 8046
8169 // Code below assumes that we don't fall through. 8047 // Code below assumes that we don't fall through.
8170 UNREACHABLE(); 8048 UNREACHABLE();
8171 } else if (op == Token::IN) { 8049 } else if (op == Token::IN) {
8172 HValue* function = AddLoadJSBuiltin(Builtins::IN, context); 8050 HValue* function = AddLoadJSBuiltin(Builtins::IN);
8173 Add<HPushArgument>(left); 8051 Add<HPushArgument>(left);
8174 Add<HPushArgument>(right); 8052 Add<HPushArgument>(right);
8175 // TODO(olivf) InvokeFunction produces a check for the parameter count, 8053 // TODO(olivf) InvokeFunction produces a check for the parameter count,
8176 // even though we are certain to pass the correct number of arguments here. 8054 // even though we are certain to pass the correct number of arguments here.
8177 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); 8055 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2);
8178 result->set_position(expr->position()); 8056 result->set_position(expr->position());
8179 return ast_context()->ReturnInstruction(result, expr->id()); 8057 return ast_context()->ReturnInstruction(result, expr->id());
8180 } 8058 }
8181 8059
8182 // Cases handled below depend on collected type feedback. They should 8060 // Cases handled below depend on collected type feedback. They should
8183 // soft deoptimize when there is no type feedback. 8061 // soft deoptimize when there is no type feedback.
8184 if (combined_type->Is(Type::None())) { 8062 if (combined_type->Is(Type::None())) {
8185 Add<HDeoptimize>(Deoptimizer::SOFT); 8063 Add<HDeoptimize>(Deoptimizer::SOFT);
8186 combined_type = left_type = right_type = handle(Type::Any(), isolate()); 8064 combined_type = left_type = right_type = handle(Type::Any(), isolate());
8187 } 8065 }
8188 8066
8189 if (combined_type->Is(Type::Receiver())) { 8067 if (combined_type->Is(Type::Receiver())) {
8190 switch (op) { 8068 switch (op) {
8191 case Token::EQ: 8069 case Token::EQ:
8192 case Token::EQ_STRICT: { 8070 case Token::EQ_STRICT: {
8193 // Can we get away with map check and not instance type check? 8071 // Can we get away with map check and not instance type check?
8194 if (combined_type->IsClass()) { 8072 if (combined_type->IsClass()) {
8195 Handle<Map> map = combined_type->AsClass(); 8073 Handle<Map> map = combined_type->AsClass();
8196 AddCheckMapsWithTransitions(left, map); 8074 AddCheckMap(left, map);
8197 AddCheckMapsWithTransitions(right, map); 8075 AddCheckMap(right, map);
8198 HCompareObjectEqAndBranch* result = 8076 HCompareObjectEqAndBranch* result =
8199 new(zone()) HCompareObjectEqAndBranch(left, right); 8077 New<HCompareObjectEqAndBranch>(left, right);
8200 result->set_position(expr->position()); 8078 result->set_position(expr->position());
8201 return ast_context()->ReturnControl(result, expr->id()); 8079 return ast_context()->ReturnControl(result, expr->id());
8202 } else { 8080 } else {
8203 BuildCheckHeapObject(left); 8081 BuildCheckHeapObject(left);
8204 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); 8082 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
8205 BuildCheckHeapObject(right); 8083 BuildCheckHeapObject(right);
8206 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); 8084 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
8207 HCompareObjectEqAndBranch* result = 8085 HCompareObjectEqAndBranch* result =
8208 new(zone()) HCompareObjectEqAndBranch(left, right); 8086 new(zone()) HCompareObjectEqAndBranch(left, right);
8209 result->set_position(expr->position()); 8087 result->set_position(expr->position());
8210 return ast_context()->ReturnControl(result, expr->id()); 8088 return ast_context()->ReturnControl(result, expr->id());
8211 } 8089 }
8212 } 8090 }
8213 default: 8091 default:
8214 return Bailout("Unsupported non-primitive compare"); 8092 return Bailout(kUnsupportedNonPrimitiveCompare);
8215 } 8093 }
8216 } else if (combined_type->Is(Type::InternalizedString()) && 8094 } else if (combined_type->Is(Type::InternalizedString()) &&
8217 Token::IsEqualityOp(op)) { 8095 Token::IsEqualityOp(op)) {
8218 BuildCheckHeapObject(left); 8096 BuildCheckHeapObject(left);
8219 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); 8097 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
8220 BuildCheckHeapObject(right); 8098 BuildCheckHeapObject(right);
8221 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); 8099 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone()));
8222 HCompareObjectEqAndBranch* result = 8100 HCompareObjectEqAndBranch* result =
8223 new(zone()) HCompareObjectEqAndBranch(left, right); 8101 new(zone()) HCompareObjectEqAndBranch(left, right);
8224 result->set_position(expr->position()); 8102 result->set_position(expr->position());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8270 ? handle(Type::Any(), isolate_) : expr->combined_type(); 8148 ? handle(Type::Any(), isolate_) : expr->combined_type();
8271 BuildCompareNil(value, type, expr->position(), &continuation); 8149 BuildCompareNil(value, type, expr->position(), &continuation);
8272 return ast_context()->ReturnContinuation(&continuation, expr->id()); 8150 return ast_context()->ReturnContinuation(&continuation, expr->id());
8273 } 8151 }
8274 8152
8275 8153
8276 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { 8154 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
8277 // If we share optimized code between different closures, the 8155 // If we share optimized code between different closures, the
8278 // this-function is not a constant, except inside an inlined body. 8156 // this-function is not a constant, except inside an inlined body.
8279 if (function_state()->outer() != NULL) { 8157 if (function_state()->outer() != NULL) {
8280 return new(zone()) HConstant( 8158 return New<HConstant>(
8281 function_state()->compilation_info()->closure()); 8159 function_state()->compilation_info()->closure());
8282 } else { 8160 } else {
8283 return new(zone()) HThisFunction; 8161 return new(zone()) HThisFunction;
8284 } 8162 }
8285 } 8163 }
8286 8164
8287 8165
8288 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( 8166 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
8289 HValue* context, 8167 HValue* context,
8290 Handle<JSObject> boilerplate_object, 8168 Handle<JSObject> boilerplate_object,
8291 Handle<JSObject> original_boilerplate_object, 8169 Handle<JSObject> original_boilerplate_object,
8292 Handle<Object> allocation_site, 8170 Handle<Object> allocation_site,
8293 int data_size, 8171 int data_size,
8294 int pointer_size, 8172 int pointer_size,
8295 AllocationSiteMode mode) { 8173 AllocationSiteMode mode) {
8296 NoObservableSideEffectsScope no_effects(this); 8174 NoObservableSideEffectsScope no_effects(this);
8297 8175
8298 HInstruction* target = NULL; 8176 HInstruction* target = NULL;
8299 HInstruction* data_target = NULL; 8177 HInstruction* data_target = NULL;
8300 8178
8301 ElementsKind kind = boilerplate_object->map()->elements_kind(); 8179 if (isolate()->heap()->GetPretenureMode() == TENURED) {
8302
8303 if (isolate()->heap()->ShouldGloballyPretenure()) {
8304 if (data_size != 0) { 8180 if (data_size != 0) {
8305 HAllocate::Flags data_flags =
8306 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags(kind) |
8307 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE);
8308 HValue* size_in_bytes = Add<HConstant>(data_size); 8181 HValue* size_in_bytes = Add<HConstant>(data_size);
8309 data_target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), 8182 data_target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED,
8310 data_flags); 8183 FIXED_DOUBLE_ARRAY_TYPE);
8311 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); 8184 Handle<Map> free_space_map = isolate()->factory()->free_space_map();
8312 AddStoreMapConstant(data_target, free_space_map); 8185 AddStoreMapConstant(data_target, free_space_map);
8313 HObjectAccess access = 8186 HObjectAccess access =
8314 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); 8187 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset);
8315 AddStore(data_target, access, size_in_bytes); 8188 Add<HStoreNamedField>(data_target, access, size_in_bytes);
8316 } 8189 }
8317 if (pointer_size != 0) { 8190 if (pointer_size != 0) {
8318 HAllocate::Flags pointer_flags =
8319 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() |
8320 HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
8321 HValue* size_in_bytes = Add<HConstant>(pointer_size); 8191 HValue* size_in_bytes = Add<HConstant>(pointer_size);
8322 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), 8192 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED,
8323 pointer_flags); 8193 JS_OBJECT_TYPE);
8324 } 8194 }
8325 } else { 8195 } else {
8326 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); 8196 InstanceType instance_type = boilerplate_object->map()->instance_type();
8327 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); 8197 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size);
8328 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); 8198 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), NOT_TENURED,
8199 instance_type);
8329 } 8200 }
8330 8201
8331 int offset = 0; 8202 int offset = 0;
8332 int data_offset = 0; 8203 int data_offset = 0;
8333 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, 8204 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object,
8334 allocation_site, target, &offset, data_target, 8205 allocation_site, target, &offset, data_target,
8335 &data_offset, mode); 8206 &data_offset, mode);
8336 return target; 8207 return target;
8337 } 8208 }
8338 8209
8339 8210
8340 void HOptimizedGraphBuilder::BuildEmitDeepCopy( 8211 void HOptimizedGraphBuilder::BuildEmitDeepCopy(
8341 Handle<JSObject> boilerplate_object, 8212 Handle<JSObject> boilerplate_object,
8342 Handle<JSObject> original_boilerplate_object, 8213 Handle<JSObject> original_boilerplate_object,
8343 Handle<Object> allocation_site_object, 8214 Handle<Object> allocation_site_object,
8344 HInstruction* target, 8215 HInstruction* target,
8345 int* offset, 8216 int* offset,
8346 HInstruction* data_target, 8217 HInstruction* data_target,
8347 int* data_offset, 8218 int* data_offset,
8348 AllocationSiteMode mode) { 8219 AllocationSiteMode mode) {
8349 Zone* zone = this->zone();
8350
8351 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && 8220 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
8352 boilerplate_object->map()->CanTrackAllocationSite(); 8221 boilerplate_object->map()->CanTrackAllocationSite();
8353 8222
8354 // If using allocation sites, then the payload on the site should already 8223 // If using allocation sites, then the payload on the site should already
8355 // be filled in as a valid (boilerplate) array. 8224 // be filled in as a valid (boilerplate) array.
8356 ASSERT(!create_allocation_site_info || 8225 ASSERT(!create_allocation_site_info ||
8357 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); 8226 AllocationSite::cast(*allocation_site_object)->IsLiteralSite());
8358 8227
8359 HInstruction* allocation_site = NULL; 8228 HInstruction* allocation_site = NULL;
8360 8229
8361 if (create_allocation_site_info) { 8230 if (create_allocation_site_info) {
8362 allocation_site = AddInstruction(new(zone) HConstant( 8231 allocation_site = Add<HConstant>(allocation_site_object);
8363 allocation_site_object, Representation::Tagged()));
8364 } 8232 }
8365 8233
8366 // Only elements backing stores for non-COW arrays need to be copied. 8234 // Only elements backing stores for non-COW arrays need to be copied.
8367 Handle<FixedArrayBase> elements(boilerplate_object->elements()); 8235 Handle<FixedArrayBase> elements(boilerplate_object->elements());
8368 Handle<FixedArrayBase> original_elements( 8236 Handle<FixedArrayBase> original_elements(
8369 original_boilerplate_object->elements()); 8237 original_boilerplate_object->elements());
8370 ElementsKind kind = boilerplate_object->map()->elements_kind(); 8238 ElementsKind kind = boilerplate_object->map()->elements_kind();
8371 8239
8372 int object_offset = *offset; 8240 int object_offset = *offset;
8373 int object_size = boilerplate_object->map()->instance_size(); 8241 int object_size = boilerplate_object->map()->instance_size();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
8434 Handle<Object>(boilerplate_object->elements(), isolate()); 8302 Handle<Object>(boilerplate_object->elements(), isolate());
8435 elements = Add<HConstant>(elements_field); 8303 elements = Add<HConstant>(elements_field);
8436 } else { 8304 } else {
8437 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { 8305 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) {
8438 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); 8306 elements = Add<HInnerAllocatedObject>(data_target, elements_offset);
8439 } else { 8307 } else {
8440 elements = Add<HInnerAllocatedObject>(target, elements_offset); 8308 elements = Add<HInnerAllocatedObject>(target, elements_offset);
8441 } 8309 }
8442 result = elements; 8310 result = elements;
8443 } 8311 }
8444 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); 8312 Add<HStoreNamedField>(object_header, HObjectAccess::ForElementsPointer(),
8313 elements);
8445 8314
8446 Handle<Object> properties_field = 8315 Handle<Object> properties_field =
8447 Handle<Object>(boilerplate_object->properties(), isolate()); 8316 Handle<Object>(boilerplate_object->properties(), isolate());
8448 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); 8317 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
8449 HInstruction* properties = Add<HConstant>(properties_field); 8318 HInstruction* properties = Add<HConstant>(properties_field);
8450 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); 8319 HObjectAccess access = HObjectAccess::ForPropertiesPointer();
8451 AddStore(object_header, access, properties); 8320 Add<HStoreNamedField>(object_header, access, properties);
8452 8321
8453 if (boilerplate_object->IsJSArray()) { 8322 if (boilerplate_object->IsJSArray()) {
8454 Handle<JSArray> boilerplate_array = 8323 Handle<JSArray> boilerplate_array =
8455 Handle<JSArray>::cast(boilerplate_object); 8324 Handle<JSArray>::cast(boilerplate_object);
8456 Handle<Object> length_field = 8325 Handle<Object> length_field =
8457 Handle<Object>(boilerplate_array->length(), isolate()); 8326 Handle<Object>(boilerplate_array->length(), isolate());
8458 HInstruction* length = Add<HConstant>(length_field); 8327 HInstruction* length = Add<HConstant>(length_field);
8459 8328
8460 ASSERT(boilerplate_array->length()->IsSmi()); 8329 ASSERT(boilerplate_array->length()->IsSmi());
8461 AddStore(object_header, HObjectAccess::ForArrayLength( 8330 Add<HStoreNamedField>(object_header, HObjectAccess::ForArrayLength(
8462 boilerplate_array->GetElementsKind()), length); 8331 boilerplate_array->GetElementsKind()), length);
8463 } 8332 }
8464 8333
8465 return result; 8334 return result;
8466 } 8335 }
8467 8336
8468 8337
8469 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( 8338 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
8470 Handle<JSObject> boilerplate_object, 8339 Handle<JSObject> boilerplate_object,
8471 Handle<JSObject> original_boilerplate_object, 8340 Handle<JSObject> original_boilerplate_object,
(...skipping 24 matching lines...) Expand all
8496 HObjectAccess::ForJSObjectOffset(property_offset); 8365 HObjectAccess::ForJSObjectOffset(property_offset);
8497 8366
8498 if (value->IsJSObject()) { 8367 if (value->IsJSObject()) {
8499 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 8368 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
8500 Handle<JSObject> original_value_object = Handle<JSObject>::cast( 8369 Handle<JSObject> original_value_object = Handle<JSObject>::cast(
8501 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), 8370 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index),
8502 isolate())); 8371 isolate()));
8503 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, 8372 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target,
8504 *offset); 8373 *offset);
8505 8374
8506 AddStore(object_properties, access, value_instruction); 8375 Add<HStoreNamedField>(object_properties, access, value_instruction);
8507 BuildEmitDeepCopy(value_object, original_value_object, 8376 BuildEmitDeepCopy(value_object, original_value_object,
8508 Handle<Object>::null(), target, 8377 Handle<Object>::null(), target,
8509 offset, data_target, data_offset, 8378 offset, data_target, data_offset,
8510 DONT_TRACK_ALLOCATION_SITE); 8379 DONT_TRACK_ALLOCATION_SITE);
8511 } else { 8380 } else {
8512 Representation representation = details.representation(); 8381 Representation representation = details.representation();
8513 HInstruction* value_instruction = Add<HConstant>(value); 8382 HInstruction* value_instruction = Add<HConstant>(value);
8514 8383
8515 if (representation.IsDouble()) { 8384 if (representation.IsDouble()) {
8516 // Allocate a HeapNumber box and store the value into it. 8385 // Allocate a HeapNumber box and store the value into it.
8517 HInstruction* double_box; 8386 HInstruction* double_box;
8518 if (data_target != NULL) { 8387 if (data_target != NULL) {
8519 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); 8388 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset);
8520 *data_offset += HeapNumber::kSize; 8389 *data_offset += HeapNumber::kSize;
8521 } else { 8390 } else {
8522 double_box = Add<HInnerAllocatedObject>(target, *offset); 8391 double_box = Add<HInnerAllocatedObject>(target, *offset);
8523 *offset += HeapNumber::kSize; 8392 *offset += HeapNumber::kSize;
8524 } 8393 }
8525 AddStoreMapConstant(double_box, 8394 AddStoreMapConstant(double_box,
8526 isolate()->factory()->heap_number_map()); 8395 isolate()->factory()->heap_number_map());
8527 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), 8396 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
8528 value_instruction); 8397 value_instruction);
8529 value_instruction = double_box; 8398 value_instruction = double_box;
8530 } 8399 }
8531 8400
8532 AddStore(object_properties, access, value_instruction); 8401 Add<HStoreNamedField>(object_properties, access, value_instruction);
8533 } 8402 }
8534 } 8403 }
8535 8404
8536 int inobject_properties = boilerplate_object->map()->inobject_properties(); 8405 int inobject_properties = boilerplate_object->map()->inobject_properties();
8537 HInstruction* value_instruction = 8406 HInstruction* value_instruction =
8538 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); 8407 Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
8539 for (int i = copied_fields; i < inobject_properties; i++) { 8408 for (int i = copied_fields; i < inobject_properties; i++) {
8540 ASSERT(boilerplate_object->IsJSObject()); 8409 ASSERT(boilerplate_object->IsJSObject());
8541 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); 8410 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
8542 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); 8411 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset);
8543 AddStore(object_properties, access, value_instruction); 8412 Add<HStoreNamedField>(object_properties, access, value_instruction);
8544 } 8413 }
8545 } 8414 }
8546 8415
8547 8416
8548 void HOptimizedGraphBuilder::BuildEmitElements( 8417 void HOptimizedGraphBuilder::BuildEmitElements(
8549 Handle<FixedArrayBase> elements, 8418 Handle<FixedArrayBase> elements,
8550 Handle<FixedArrayBase> original_elements, 8419 Handle<FixedArrayBase> original_elements,
8551 ElementsKind kind, 8420 ElementsKind kind,
8552 HValue* object_elements, 8421 HValue* object_elements,
8553 HInstruction* target, 8422 HInstruction* target,
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
8642 ZoneList<Declaration*>* declarations) { 8511 ZoneList<Declaration*>* declarations) {
8643 ASSERT(globals_.is_empty()); 8512 ASSERT(globals_.is_empty());
8644 AstVisitor::VisitDeclarations(declarations); 8513 AstVisitor::VisitDeclarations(declarations);
8645 if (!globals_.is_empty()) { 8514 if (!globals_.is_empty()) {
8646 Handle<FixedArray> array = 8515 Handle<FixedArray> array =
8647 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); 8516 isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
8648 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); 8517 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
8649 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | 8518 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
8650 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | 8519 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
8651 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); 8520 DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
8652 Add<HDeclareGlobals>(environment()->LookupContext(), array, flags); 8521 Add<HDeclareGlobals>(array, flags);
8653 globals_.Clear(); 8522 globals_.Clear();
8654 } 8523 }
8655 } 8524 }
8656 8525
8657 8526
8658 void HOptimizedGraphBuilder::VisitVariableDeclaration( 8527 void HOptimizedGraphBuilder::VisitVariableDeclaration(
8659 VariableDeclaration* declaration) { 8528 VariableDeclaration* declaration) {
8660 VariableProxy* proxy = declaration->proxy(); 8529 VariableProxy* proxy = declaration->proxy();
8661 VariableMode mode = declaration->mode(); 8530 VariableMode mode = declaration->mode();
8662 Variable* variable = proxy->var(); 8531 Variable* variable = proxy->var();
8663 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; 8532 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
8664 switch (variable->location()) { 8533 switch (variable->location()) {
8665 case Variable::UNALLOCATED: 8534 case Variable::UNALLOCATED:
8666 globals_.Add(variable->name(), zone()); 8535 globals_.Add(variable->name(), zone());
8667 globals_.Add(variable->binding_needs_init() 8536 globals_.Add(variable->binding_needs_init()
8668 ? isolate()->factory()->the_hole_value() 8537 ? isolate()->factory()->the_hole_value()
8669 : isolate()->factory()->undefined_value(), zone()); 8538 : isolate()->factory()->undefined_value(), zone());
8670 return; 8539 return;
8671 case Variable::PARAMETER: 8540 case Variable::PARAMETER:
8672 case Variable::LOCAL: 8541 case Variable::LOCAL:
8673 if (hole_init) { 8542 if (hole_init) {
8674 HValue* value = graph()->GetConstantHole(); 8543 HValue* value = graph()->GetConstantHole();
8675 environment()->Bind(variable, value); 8544 environment()->Bind(variable, value);
8676 } 8545 }
8677 break; 8546 break;
8678 case Variable::CONTEXT: 8547 case Variable::CONTEXT:
8679 if (hole_init) { 8548 if (hole_init) {
8680 HValue* value = graph()->GetConstantHole(); 8549 HValue* value = graph()->GetConstantHole();
8681 HValue* context = environment()->LookupContext(); 8550 HValue* context = environment()->context();
8682 HStoreContextSlot* store = Add<HStoreContextSlot>( 8551 HStoreContextSlot* store = Add<HStoreContextSlot>(
8683 context, variable->index(), HStoreContextSlot::kNoCheck, value); 8552 context, variable->index(), HStoreContextSlot::kNoCheck, value);
8684 if (store->HasObservableSideEffects()) { 8553 if (store->HasObservableSideEffects()) {
8685 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); 8554 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
8686 } 8555 }
8687 } 8556 }
8688 break; 8557 break;
8689 case Variable::LOOKUP: 8558 case Variable::LOOKUP:
8690 return Bailout("unsupported lookup slot in declaration"); 8559 return Bailout(kUnsupportedLookupSlotInDeclaration);
8691 } 8560 }
8692 } 8561 }
8693 8562
8694 8563
8695 void HOptimizedGraphBuilder::VisitFunctionDeclaration( 8564 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
8696 FunctionDeclaration* declaration) { 8565 FunctionDeclaration* declaration) {
8697 VariableProxy* proxy = declaration->proxy(); 8566 VariableProxy* proxy = declaration->proxy();
8698 Variable* variable = proxy->var(); 8567 Variable* variable = proxy->var();
8699 switch (variable->location()) { 8568 switch (variable->location()) {
8700 case Variable::UNALLOCATED: { 8569 case Variable::UNALLOCATED: {
8701 globals_.Add(variable->name(), zone()); 8570 globals_.Add(variable->name(), zone());
8702 Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo( 8571 Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo(
8703 declaration->fun(), current_info()->script()); 8572 declaration->fun(), current_info()->script());
8704 // Check for stack-overflow exception. 8573 // Check for stack-overflow exception.
8705 if (function.is_null()) return SetStackOverflow(); 8574 if (function.is_null()) return SetStackOverflow();
8706 globals_.Add(function, zone()); 8575 globals_.Add(function, zone());
8707 return; 8576 return;
8708 } 8577 }
8709 case Variable::PARAMETER: 8578 case Variable::PARAMETER:
8710 case Variable::LOCAL: { 8579 case Variable::LOCAL: {
8711 CHECK_ALIVE(VisitForValue(declaration->fun())); 8580 CHECK_ALIVE(VisitForValue(declaration->fun()));
8712 HValue* value = Pop(); 8581 HValue* value = Pop();
8713 BindIfLive(variable, value); 8582 BindIfLive(variable, value);
8714 break; 8583 break;
8715 } 8584 }
8716 case Variable::CONTEXT: { 8585 case Variable::CONTEXT: {
8717 CHECK_ALIVE(VisitForValue(declaration->fun())); 8586 CHECK_ALIVE(VisitForValue(declaration->fun()));
8718 HValue* value = Pop(); 8587 HValue* value = Pop();
8719 HValue* context = environment()->LookupContext(); 8588 HValue* context = environment()->context();
8720 HStoreContextSlot* store = Add<HStoreContextSlot>( 8589 HStoreContextSlot* store = Add<HStoreContextSlot>(
8721 context, variable->index(), HStoreContextSlot::kNoCheck, value); 8590 context, variable->index(), HStoreContextSlot::kNoCheck, value);
8722 if (store->HasObservableSideEffects()) { 8591 if (store->HasObservableSideEffects()) {
8723 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); 8592 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
8724 } 8593 }
8725 break; 8594 break;
8726 } 8595 }
8727 case Variable::LOOKUP: 8596 case Variable::LOOKUP:
8728 return Bailout("unsupported lookup slot in declaration"); 8597 return Bailout(kUnsupportedLookupSlotInDeclaration);
8729 } 8598 }
8730 } 8599 }
8731 8600
8732 8601
8733 void HOptimizedGraphBuilder::VisitModuleDeclaration( 8602 void HOptimizedGraphBuilder::VisitModuleDeclaration(
8734 ModuleDeclaration* declaration) { 8603 ModuleDeclaration* declaration) {
8735 UNREACHABLE(); 8604 UNREACHABLE();
8736 } 8605 }
8737 8606
8738 8607
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
8839 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { 8708 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
8840 ASSERT(call->arguments()->length() == 1); 8709 ASSERT(call->arguments()->length() == 1);
8841 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8710 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8842 HValue* value = Pop(); 8711 HValue* value = Pop();
8843 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); 8712 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value);
8844 return ast_context()->ReturnControl(result, call->id()); 8713 return ast_context()->ReturnControl(result, call->id());
8845 } 8714 }
8846 8715
8847 8716
8848 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { 8717 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
8849 return Bailout("inlined runtime function: IsNonNegativeSmi"); 8718 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
8850 } 8719 }
8851 8720
8852 8721
8853 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { 8722 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
8854 ASSERT(call->arguments()->length() == 1); 8723 ASSERT(call->arguments()->length() == 1);
8855 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8724 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8856 HValue* value = Pop(); 8725 HValue* value = Pop();
8857 HIsUndetectableAndBranch* result = 8726 HIsUndetectableAndBranch* result =
8858 new(zone()) HIsUndetectableAndBranch(value); 8727 new(zone()) HIsUndetectableAndBranch(value);
8859 return ast_context()->ReturnControl(result, call->id()); 8728 return ast_context()->ReturnControl(result, call->id());
8860 } 8729 }
8861 8730
8862 8731
8863 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 8732 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
8864 CallRuntime* call) { 8733 CallRuntime* call) {
8865 return Bailout( 8734 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
8866 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
8867 } 8735 }
8868 8736
8869 8737
8870 // Support for construct call checks. 8738 // Support for construct call checks.
8871 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 8739 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
8872 ASSERT(call->arguments()->length() == 0); 8740 ASSERT(call->arguments()->length() == 0);
8873 if (function_state()->outer() != NULL) { 8741 if (function_state()->outer() != NULL) {
8874 // We are generating graph for inlined function. 8742 // We are generating graph for inlined function.
8875 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN 8743 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
8876 ? graph()->GetConstantTrue() 8744 ? graph()->GetConstantTrue()
8877 : graph()->GetConstantFalse(); 8745 : graph()->GetConstantFalse();
8878 return ast_context()->ReturnValue(value); 8746 return ast_context()->ReturnValue(value);
8879 } else { 8747 } else {
8880 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 8748 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
8881 call->id()); 8749 call->id());
8882 } 8750 }
8883 } 8751 }
8884 8752
8885 8753
8886 // Support for arguments.length and arguments[?]. 8754 // Support for arguments.length and arguments[?].
8887 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 8755 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
8888 // Our implementation of arguments (based on this stack frame or an 8756 // Our implementation of arguments (based on this stack frame or an
8889 // adapter below it) does not work for inlined functions. This runtime 8757 // adapter below it) does not work for inlined functions. This runtime
8890 // function is blacklisted by AstNode::IsInlineable. 8758 // function is blacklisted by AstNode::IsInlineable.
8891 ASSERT(function_state()->outer() == NULL); 8759 ASSERT(function_state()->outer() == NULL);
8892 ASSERT(call->arguments()->length() == 0); 8760 ASSERT(call->arguments()->length() == 0);
8893 HInstruction* elements = Add<HArgumentsElements>(false); 8761 HInstruction* elements = Add<HArgumentsElements>(false);
8894 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); 8762 HArgumentsLength* result = New<HArgumentsLength>(elements);
8895 return ast_context()->ReturnInstruction(result, call->id()); 8763 return ast_context()->ReturnInstruction(result, call->id());
8896 } 8764 }
8897 8765
8898 8766
8899 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { 8767 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
8900 // Our implementation of arguments (based on this stack frame or an 8768 // Our implementation of arguments (based on this stack frame or an
8901 // adapter below it) does not work for inlined functions. This runtime 8769 // adapter below it) does not work for inlined functions. This runtime
8902 // function is blacklisted by AstNode::IsInlineable. 8770 // function is blacklisted by AstNode::IsInlineable.
8903 ASSERT(function_state()->outer() == NULL); 8771 ASSERT(function_state()->outer() == NULL);
8904 ASSERT(call->arguments()->length() == 1); 8772 ASSERT(call->arguments()->length() == 1);
8905 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8773 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8906 HValue* index = Pop(); 8774 HValue* index = Pop();
8907 HInstruction* elements = Add<HArgumentsElements>(false); 8775 HInstruction* elements = Add<HArgumentsElements>(false);
8908 HInstruction* length = Add<HArgumentsLength>(elements); 8776 HInstruction* length = Add<HArgumentsLength>(elements);
8909 HInstruction* checked_index = Add<HBoundsCheck>(index, length); 8777 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
8910 HAccessArgumentsAt* result = 8778 HAccessArgumentsAt* result =
8911 new(zone()) HAccessArgumentsAt(elements, length, checked_index); 8779 new(zone()) HAccessArgumentsAt(elements, length, checked_index);
8912 return ast_context()->ReturnInstruction(result, call->id()); 8780 return ast_context()->ReturnInstruction(result, call->id());
8913 } 8781 }
8914 8782
8915 8783
8916 // Support for accessing the class and value fields of an object. 8784 // Support for accessing the class and value fields of an object.
8917 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { 8785 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
8918 // The special form detected by IsClassOfTest is detected before we get here 8786 // The special form detected by IsClassOfTest is detected before we get here
8919 // and does not cause a bailout. 8787 // and does not cause a bailout.
8920 return Bailout("inlined runtime function: ClassOf"); 8788 return Bailout(kInlinedRuntimeFunctionClassOf);
8921 } 8789 }
8922 8790
8923 8791
8924 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { 8792 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
8925 ASSERT(call->arguments()->length() == 1); 8793 ASSERT(call->arguments()->length() == 1);
8926 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8794 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8927 HValue* value = Pop(); 8795 HValue* value = Pop();
8928 HValueOf* result = new(zone()) HValueOf(value); 8796 HValueOf* result = new(zone()) HValueOf(value);
8929 return ast_context()->ReturnInstruction(result, call->id()); 8797 return ast_context()->ReturnInstruction(result, call->id());
8930 } 8798 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
8993 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); 8861 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE);
8994 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); 8862 HBasicBlock* if_js_value = graph()->CreateBasicBlock();
8995 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); 8863 HBasicBlock* not_js_value = graph()->CreateBasicBlock();
8996 typecheck->SetSuccessorAt(0, if_js_value); 8864 typecheck->SetSuccessorAt(0, if_js_value);
8997 typecheck->SetSuccessorAt(1, not_js_value); 8865 typecheck->SetSuccessorAt(1, not_js_value);
8998 current_block()->Finish(typecheck); 8866 current_block()->Finish(typecheck);
8999 not_js_value->Goto(join); 8867 not_js_value->Goto(join);
9000 8868
9001 // Create in-object property store to kValueOffset. 8869 // Create in-object property store to kValueOffset.
9002 set_current_block(if_js_value); 8870 set_current_block(if_js_value);
9003 AddStore(object, 8871 Add<HStoreNamedField>(object,
9004 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); 8872 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value);
9005 if_js_value->Goto(join); 8873 if_js_value->Goto(join);
9006 join->SetJoinId(call->id()); 8874 join->SetJoinId(call->id());
9007 set_current_block(join); 8875 set_current_block(join);
9008 return ast_context()->ReturnValue(value); 8876 return ast_context()->ReturnValue(value);
9009 } 8877 }
9010 8878
9011 8879
9012 // Fast support for charCodeAt(n). 8880 // Fast support for charCodeAt(n).
9013 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 8881 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
9014 ASSERT(call->arguments()->length() == 2); 8882 ASSERT(call->arguments()->length() == 2);
9015 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8883 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9016 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8884 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9017 HValue* index = Pop(); 8885 HValue* index = Pop();
9018 HValue* string = Pop(); 8886 HValue* string = Pop();
9019 HValue* context = environment()->LookupContext(); 8887 HInstruction* result = BuildStringCharCodeAt(string, index);
9020 HInstruction* result = BuildStringCharCodeAt(context, string, index);
9021 return ast_context()->ReturnInstruction(result, call->id()); 8888 return ast_context()->ReturnInstruction(result, call->id());
9022 } 8889 }
9023 8890
9024 8891
9025 // Fast support for string.charAt(n) and string[n]. 8892 // Fast support for string.charAt(n) and string[n].
9026 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { 8893 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
9027 ASSERT(call->arguments()->length() == 1); 8894 ASSERT(call->arguments()->length() == 1);
9028 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8895 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9029 HValue* char_code = Pop(); 8896 HValue* char_code = Pop();
9030 HValue* context = environment()->LookupContext(); 8897 HInstruction* result = New<HStringCharFromCode>(char_code);
9031 HInstruction* result = HStringCharFromCode::New(zone(), context, char_code);
9032 return ast_context()->ReturnInstruction(result, call->id()); 8898 return ast_context()->ReturnInstruction(result, call->id());
9033 } 8899 }
9034 8900
9035 8901
9036 // Fast support for string.charAt(n) and string[n]. 8902 // Fast support for string.charAt(n) and string[n].
9037 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { 8903 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
9038 ASSERT(call->arguments()->length() == 2); 8904 ASSERT(call->arguments()->length() == 2);
9039 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8905 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9040 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8906 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9041 HValue* index = Pop(); 8907 HValue* index = Pop();
9042 HValue* string = Pop(); 8908 HValue* string = Pop();
9043 HValue* context = environment()->LookupContext(); 8909 HInstruction* char_code = BuildStringCharCodeAt(string, index);
9044 HInstruction* char_code = BuildStringCharCodeAt(context, string, index);
9045 AddInstruction(char_code); 8910 AddInstruction(char_code);
9046 HInstruction* result = HStringCharFromCode::New(zone(), context, char_code); 8911 HInstruction* result = New<HStringCharFromCode>(char_code);
9047 return ast_context()->ReturnInstruction(result, call->id()); 8912 return ast_context()->ReturnInstruction(result, call->id());
9048 } 8913 }
9049 8914
9050 8915
9051 // Fast support for object equality testing. 8916 // Fast support for object equality testing.
9052 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { 8917 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
9053 ASSERT(call->arguments()->length() == 2); 8918 ASSERT(call->arguments()->length() == 2);
9054 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8919 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9055 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8920 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9056 HValue* right = Pop(); 8921 HValue* right = Pop();
9057 HValue* left = Pop(); 8922 HValue* left = Pop();
9058 HCompareObjectEqAndBranch* result = 8923 HCompareObjectEqAndBranch* result =
9059 new(zone()) HCompareObjectEqAndBranch(left, right); 8924 New<HCompareObjectEqAndBranch>(left, right);
9060 return ast_context()->ReturnControl(result, call->id()); 8925 return ast_context()->ReturnControl(result, call->id());
9061 } 8926 }
9062 8927
9063 8928
9064 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { 8929 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
9065 // %_Log is ignored in optimized code. 8930 // %_Log is ignored in optimized code.
9066 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 8931 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9067 } 8932 }
9068 8933
9069 8934
9070 // Fast support for Math.random(). 8935 // Fast support for Math.random().
9071 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 8936 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
9072 HValue* context = environment()->LookupContext(); 8937 HGlobalObject* global_object = Add<HGlobalObject>();
9073 HGlobalObject* global_object = Add<HGlobalObject>(context);
9074 HRandom* result = new(zone()) HRandom(global_object); 8938 HRandom* result = new(zone()) HRandom(global_object);
9075 return ast_context()->ReturnInstruction(result, call->id()); 8939 return ast_context()->ReturnInstruction(result, call->id());
9076 } 8940 }
9077 8941
9078 8942
9079 // Fast support for StringAdd. 8943 // Fast support for StringAdd.
9080 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { 8944 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
9081 ASSERT_EQ(2, call->arguments()->length()); 8945 ASSERT_EQ(2, call->arguments()->length());
9082 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8946 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9083 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8947 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9084 HValue* right = Pop(); 8948 HValue* right = Pop();
9085 HValue* left = Pop(); 8949 HValue* left = Pop();
9086 HValue* context = environment()->LookupContext(); 8950 HValue* context = environment()->context();
9087 HInstruction* result = HStringAdd::New( 8951 HInstruction* result = HStringAdd::New(
9088 zone(), context, left, right, STRING_ADD_CHECK_BOTH); 8952 zone(), context, left, right, STRING_ADD_CHECK_BOTH);
9089 return ast_context()->ReturnInstruction(result, call->id()); 8953 return ast_context()->ReturnInstruction(result, call->id());
9090 } 8954 }
9091 8955
9092 8956
9093 // Fast support for SubString. 8957 // Fast support for SubString.
9094 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { 8958 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
9095 ASSERT_EQ(3, call->arguments()->length()); 8959 ASSERT_EQ(3, call->arguments()->length());
9096 CHECK_ALIVE(VisitArgumentList(call->arguments())); 8960 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9097 HValue* context = environment()->LookupContext(); 8961 HValue* context = environment()->context();
9098 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); 8962 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
9099 Drop(3); 8963 Drop(3);
9100 return ast_context()->ReturnInstruction(result, call->id()); 8964 return ast_context()->ReturnInstruction(result, call->id());
9101 } 8965 }
9102 8966
9103 8967
9104 // Fast support for StringCompare. 8968 // Fast support for StringCompare.
9105 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { 8969 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
9106 ASSERT_EQ(2, call->arguments()->length()); 8970 ASSERT_EQ(2, call->arguments()->length());
9107 CHECK_ALIVE(VisitArgumentList(call->arguments())); 8971 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9108 HValue* context = environment()->LookupContext(); 8972 HValue* context = environment()->context();
9109 HCallStub* result = 8973 HCallStub* result =
9110 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); 8974 new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
9111 Drop(2); 8975 Drop(2);
9112 return ast_context()->ReturnInstruction(result, call->id()); 8976 return ast_context()->ReturnInstruction(result, call->id());
9113 } 8977 }
9114 8978
9115 8979
9116 // Support for direct calls from JavaScript to native RegExp code. 8980 // Support for direct calls from JavaScript to native RegExp code.
9117 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { 8981 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
9118 ASSERT_EQ(4, call->arguments()->length()); 8982 ASSERT_EQ(4, call->arguments()->length());
9119 CHECK_ALIVE(VisitArgumentList(call->arguments())); 8983 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9120 HValue* context = environment()->LookupContext(); 8984 HValue* context = environment()->context();
9121 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); 8985 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
9122 Drop(4); 8986 Drop(4);
9123 return ast_context()->ReturnInstruction(result, call->id()); 8987 return ast_context()->ReturnInstruction(result, call->id());
9124 } 8988 }
9125 8989
9126 8990
9127 // Construct a RegExp exec result with two in-object properties. 8991 // Construct a RegExp exec result with two in-object properties.
9128 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { 8992 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
9129 ASSERT_EQ(3, call->arguments()->length()); 8993 ASSERT_EQ(3, call->arguments()->length());
9130 CHECK_ALIVE(VisitArgumentList(call->arguments())); 8994 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9131 HValue* context = environment()->LookupContext(); 8995 HValue* context = environment()->context();
9132 HCallStub* result = 8996 HCallStub* result =
9133 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); 8997 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
9134 Drop(3); 8998 Drop(3);
9135 return ast_context()->ReturnInstruction(result, call->id()); 8999 return ast_context()->ReturnInstruction(result, call->id());
9136 } 9000 }
9137 9001
9138 9002
9139 // Support for fast native caches. 9003 // Support for fast native caches.
9140 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 9004 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
9141 return Bailout("inlined runtime function: GetFromCache"); 9005 return Bailout(kInlinedRuntimeFunctionGetFromCache);
9142 } 9006 }
9143 9007
9144 9008
9145 // Fast support for number to string. 9009 // Fast support for number to string.
9146 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { 9010 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
9147 ASSERT_EQ(1, call->arguments()->length()); 9011 ASSERT_EQ(1, call->arguments()->length());
9148 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9012 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9149 HValue* context = environment()->LookupContext(); 9013 HValue* context = environment()->context();
9150 HCallStub* result = 9014 HCallStub* result =
9151 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); 9015 new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
9152 Drop(1); 9016 Drop(1);
9153 return ast_context()->ReturnInstruction(result, call->id()); 9017 return ast_context()->ReturnInstruction(result, call->id());
9154 } 9018 }
9155 9019
9156 9020
9157 // Fast call for custom callbacks. 9021 // Fast call for custom callbacks.
9158 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { 9022 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
9159 // 1 ~ The function to call is not itself an argument to the call. 9023 // 1 ~ The function to call is not itself an argument to the call.
9160 int arg_count = call->arguments()->length() - 1; 9024 int arg_count = call->arguments()->length() - 1;
9161 ASSERT(arg_count >= 1); // There's always at least a receiver. 9025 ASSERT(arg_count >= 1); // There's always at least a receiver.
9162 9026
9163 for (int i = 0; i < arg_count; ++i) { 9027 for (int i = 0; i < arg_count; ++i) {
9164 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 9028 CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
9165 } 9029 }
9166 CHECK_ALIVE(VisitForValue(call->arguments()->last())); 9030 CHECK_ALIVE(VisitForValue(call->arguments()->last()));
9167 9031
9168 HValue* function = Pop(); 9032 HValue* function = Pop();
9169 HValue* context = environment()->LookupContext();
9170 9033
9171 // Branch for function proxies, or other non-functions. 9034 // Branch for function proxies, or other non-functions.
9172 HHasInstanceTypeAndBranch* typecheck = 9035 HHasInstanceTypeAndBranch* typecheck =
9173 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); 9036 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE);
9174 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); 9037 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock();
9175 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); 9038 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock();
9176 HBasicBlock* join = graph()->CreateBasicBlock(); 9039 HBasicBlock* join = graph()->CreateBasicBlock();
9177 typecheck->SetSuccessorAt(0, if_jsfunction); 9040 typecheck->SetSuccessorAt(0, if_jsfunction);
9178 typecheck->SetSuccessorAt(1, if_nonfunction); 9041 typecheck->SetSuccessorAt(1, if_nonfunction);
9179 current_block()->Finish(typecheck); 9042 current_block()->Finish(typecheck);
9180 9043
9181 set_current_block(if_jsfunction); 9044 set_current_block(if_jsfunction);
9182 HInstruction* invoke_result = 9045 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count);
9183 Add<HInvokeFunction>(context, function, arg_count);
9184 Drop(arg_count); 9046 Drop(arg_count);
9185 Push(invoke_result); 9047 Push(invoke_result);
9186 if_jsfunction->Goto(join); 9048 if_jsfunction->Goto(join);
9187 9049
9188 set_current_block(if_nonfunction); 9050 set_current_block(if_nonfunction);
9189 HInstruction* call_result = Add<HCallFunction>(context, function, arg_count); 9051 HInstruction* call_result = Add<HCallFunction>(function, arg_count);
9190 Drop(arg_count); 9052 Drop(arg_count);
9191 Push(call_result); 9053 Push(call_result);
9192 if_nonfunction->Goto(join); 9054 if_nonfunction->Goto(join);
9193 9055
9194 set_current_block(join); 9056 set_current_block(join);
9195 join->SetJoinId(call->id()); 9057 join->SetJoinId(call->id());
9196 return ast_context()->ReturnValue(Pop()); 9058 return ast_context()->ReturnValue(Pop());
9197 } 9059 }
9198 9060
9199 9061
9200 // Fast call to math functions. 9062 // Fast call to math functions.
9201 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { 9063 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
9202 ASSERT_EQ(2, call->arguments()->length()); 9064 ASSERT_EQ(2, call->arguments()->length());
9203 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9065 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9204 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 9066 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
9205 HValue* right = Pop(); 9067 HValue* right = Pop();
9206 HValue* left = Pop(); 9068 HValue* left = Pop();
9207 HInstruction* result = HPower::New(zone(), left, right); 9069 HInstruction* result = HPower::New(zone(), context(), left, right);
9208 return ast_context()->ReturnInstruction(result, call->id()); 9070 return ast_context()->ReturnInstruction(result, call->id());
9209 } 9071 }
9210 9072
9211 9073
9212 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { 9074 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) {
9213 ASSERT_EQ(1, call->arguments()->length()); 9075 ASSERT_EQ(1, call->arguments()->length());
9214 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9076 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9215 HValue* context = environment()->LookupContext(); 9077 HValue* context = environment()->context();
9216 HCallStub* result = 9078 HCallStub* result =
9217 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 9079 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9218 result->set_transcendental_type(TranscendentalCache::SIN); 9080 result->set_transcendental_type(TranscendentalCache::SIN);
9219 Drop(1); 9081 Drop(1);
9220 return ast_context()->ReturnInstruction(result, call->id()); 9082 return ast_context()->ReturnInstruction(result, call->id());
9221 } 9083 }
9222 9084
9223 9085
9224 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { 9086 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) {
9225 ASSERT_EQ(1, call->arguments()->length()); 9087 ASSERT_EQ(1, call->arguments()->length());
9226 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9088 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9227 HValue* context = environment()->LookupContext(); 9089 HValue* context = environment()->context();
9228 HCallStub* result = 9090 HCallStub* result =
9229 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 9091 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9230 result->set_transcendental_type(TranscendentalCache::COS); 9092 result->set_transcendental_type(TranscendentalCache::COS);
9231 Drop(1); 9093 Drop(1);
9232 return ast_context()->ReturnInstruction(result, call->id()); 9094 return ast_context()->ReturnInstruction(result, call->id());
9233 } 9095 }
9234 9096
9235 9097
9236 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { 9098 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) {
9237 ASSERT_EQ(1, call->arguments()->length()); 9099 ASSERT_EQ(1, call->arguments()->length());
9238 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9100 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9239 HValue* context = environment()->LookupContext(); 9101 HValue* context = environment()->context();
9240 HCallStub* result = 9102 HCallStub* result =
9241 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 9103 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9242 result->set_transcendental_type(TranscendentalCache::TAN); 9104 result->set_transcendental_type(TranscendentalCache::TAN);
9243 Drop(1); 9105 Drop(1);
9244 return ast_context()->ReturnInstruction(result, call->id()); 9106 return ast_context()->ReturnInstruction(result, call->id());
9245 } 9107 }
9246 9108
9247 9109
9248 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { 9110 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) {
9249 ASSERT_EQ(1, call->arguments()->length()); 9111 ASSERT_EQ(1, call->arguments()->length());
9250 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9112 CHECK_ALIVE(VisitArgumentList(call->arguments()));
9251 HValue* context = environment()->LookupContext(); 9113 HValue* context = environment()->context();
9252 HCallStub* result = 9114 HCallStub* result =
9253 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 9115 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
9254 result->set_transcendental_type(TranscendentalCache::LOG); 9116 result->set_transcendental_type(TranscendentalCache::LOG);
9255 Drop(1); 9117 Drop(1);
9256 return ast_context()->ReturnInstruction(result, call->id()); 9118 return ast_context()->ReturnInstruction(result, call->id());
9257 } 9119 }
9258 9120
9259 9121
9260 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 9122 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
9261 ASSERT(call->arguments()->length() == 1); 9123 ASSERT(call->arguments()->length() == 1);
9262 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9124 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9263 HValue* value = Pop(); 9125 HValue* value = Pop();
9264 HValue* context = environment()->LookupContext(); 9126 HValue* context = environment()->context();
9265 HInstruction* result = 9127 HInstruction* result =
9266 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); 9128 HUnaryMathOperation::New(zone(), context, value, kMathSqrt);
9267 return ast_context()->ReturnInstruction(result, call->id()); 9129 return ast_context()->ReturnInstruction(result, call->id());
9268 } 9130 }
9269 9131
9270 9132
9271 // Check whether two RegExps are equivalent 9133 // Check whether two RegExps are equivalent
9272 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { 9134 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
9273 return Bailout("inlined runtime function: IsRegExpEquivalent"); 9135 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent);
9274 } 9136 }
9275 9137
9276 9138
9277 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 9139 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
9278 ASSERT(call->arguments()->length() == 1); 9140 ASSERT(call->arguments()->length() == 1);
9279 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9141 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9280 HValue* value = Pop(); 9142 HValue* value = Pop();
9281 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); 9143 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
9282 return ast_context()->ReturnInstruction(result, call->id()); 9144 return ast_context()->ReturnInstruction(result, call->id());
9283 } 9145 }
9284 9146
9285 9147
9286 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 9148 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
9287 return Bailout("inlined runtime function: FastAsciiArrayJoin"); 9149 return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin);
9288 } 9150 }
9289 9151
9290 9152
9291 // Support for generators. 9153 // Support for generators.
9292 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { 9154 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
9293 return Bailout("inlined runtime function: GeneratorNext"); 9155 return Bailout(kInlinedRuntimeFunctionGeneratorNext);
9294 } 9156 }
9295 9157
9296 9158
9297 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { 9159 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
9298 return Bailout("inlined runtime function: GeneratorThrow"); 9160 return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
9299 } 9161 }
9300 9162
9301 9163
9302 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( 9164 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
9303 CallRuntime* call) { 9165 CallRuntime* call) {
9304 AddInstruction(new(zone()) HDebugBreak()); 9166 AddInstruction(new(zone()) HDebugBreak());
9305 return ast_context()->ReturnValue(graph()->GetConstant0()); 9167 return ast_context()->ReturnValue(graph()->GetConstant0());
9306 } 9168 }
9307 9169
9308 9170
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
9564 HValue* push = (i <= arguments) ? 9426 HValue* push = (i <= arguments) ?
9565 ExpressionStackAt(arguments - i) : undefined; 9427 ExpressionStackAt(arguments - i) : undefined;
9566 inner->SetValueAt(i, push); 9428 inner->SetValueAt(i, push);
9567 } 9429 }
9568 // If the function we are inlining is a strict mode function or a 9430 // If the function we are inlining is a strict mode function or a
9569 // builtin function, pass undefined as the receiver for function 9431 // builtin function, pass undefined as the receiver for function
9570 // calls (instead of the global receiver). 9432 // calls (instead of the global receiver).
9571 if (undefined_receiver) { 9433 if (undefined_receiver) {
9572 inner->SetValueAt(0, undefined); 9434 inner->SetValueAt(0, undefined);
9573 } 9435 }
9574 inner->SetValueAt(arity + 1, LookupContext()); 9436 inner->SetValueAt(arity + 1, context());
9575 for (int i = arity + 2; i < inner->length(); ++i) { 9437 for (int i = arity + 2; i < inner->length(); ++i) {
9576 inner->SetValueAt(i, undefined); 9438 inner->SetValueAt(i, undefined);
9577 } 9439 }
9578 9440
9579 inner->set_ast_id(BailoutId::FunctionEntry()); 9441 inner->set_ast_id(BailoutId::FunctionEntry());
9580 return inner; 9442 return inner;
9581 } 9443 }
9582 9444
9583 9445
9584 void HEnvironment::PrintTo(StringStream* stream) { 9446 void HEnvironment::PrintTo(StringStream* stream) {
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
9914 if (ShouldProduceTraceOutput()) { 9776 if (ShouldProduceTraceOutput()) {
9915 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9777 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9916 } 9778 }
9917 9779
9918 #ifdef DEBUG 9780 #ifdef DEBUG
9919 graph_->Verify(false); // No full verify. 9781 graph_->Verify(false); // No full verify.
9920 #endif 9782 #endif
9921 } 9783 }
9922 9784
9923 } } // namespace v8::internal 9785 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-bce.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698