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

Side by Side Diff: src/hydrogen.cc

Issue 178223011: Reset trunk to 3.24.35.4 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 6 years, 9 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 #include "runtime.h" 61 #include "runtime.h"
62 #include "scopeinfo.h" 62 #include "scopeinfo.h"
63 #include "scopes.h" 63 #include "scopes.h"
64 #include "stub-cache.h" 64 #include "stub-cache.h"
65 #include "typing.h" 65 #include "typing.h"
66 66
67 #if V8_TARGET_ARCH_IA32 67 #if V8_TARGET_ARCH_IA32
68 #include "ia32/lithium-codegen-ia32.h" 68 #include "ia32/lithium-codegen-ia32.h"
69 #elif V8_TARGET_ARCH_X64 69 #elif V8_TARGET_ARCH_X64
70 #include "x64/lithium-codegen-x64.h" 70 #include "x64/lithium-codegen-x64.h"
71 #elif V8_TARGET_ARCH_A64
72 #include "a64/lithium-codegen-a64.h"
73 #elif V8_TARGET_ARCH_ARM 71 #elif V8_TARGET_ARCH_ARM
74 #include "arm/lithium-codegen-arm.h" 72 #include "arm/lithium-codegen-arm.h"
75 #elif V8_TARGET_ARCH_MIPS 73 #elif V8_TARGET_ARCH_MIPS
76 #include "mips/lithium-codegen-mips.h" 74 #include "mips/lithium-codegen-mips.h"
77 #else 75 #else
78 #error Unsupported target architecture. 76 #error Unsupported target architecture.
79 #endif 77 #endif
80 78
81 namespace v8 { 79 namespace v8 {
82 namespace internal { 80 namespace internal {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 134
137 void HBasicBlock::RemovePhi(HPhi* phi) { 135 void HBasicBlock::RemovePhi(HPhi* phi) {
138 ASSERT(phi->block() == this); 136 ASSERT(phi->block() == this);
139 ASSERT(phis_.Contains(phi)); 137 ASSERT(phis_.Contains(phi));
140 phi->Kill(); 138 phi->Kill();
141 phis_.RemoveElement(phi); 139 phis_.RemoveElement(phi);
142 phi->SetBlock(NULL); 140 phi->SetBlock(NULL);
143 } 141 }
144 142
145 143
146 void HBasicBlock::AddInstruction(HInstruction* instr, 144 void HBasicBlock::AddInstruction(HInstruction* instr, int position) {
147 HSourcePosition position) {
148 ASSERT(!IsStartBlock() || !IsFinished()); 145 ASSERT(!IsStartBlock() || !IsFinished());
149 ASSERT(!instr->IsLinked()); 146 ASSERT(!instr->IsLinked());
150 ASSERT(!IsFinished()); 147 ASSERT(!IsFinished());
151 148
152 if (!position.IsUnknown()) { 149 if (position != RelocInfo::kNoPosition) {
153 instr->set_position(position); 150 instr->set_position(position);
154 } 151 }
155 if (first_ == NULL) { 152 if (first_ == NULL) {
156 ASSERT(last_environment() != NULL); 153 ASSERT(last_environment() != NULL);
157 ASSERT(!last_environment()->ast_id().IsNone()); 154 ASSERT(!last_environment()->ast_id().IsNone());
158 HBlockEntry* entry = new(zone()) HBlockEntry(); 155 HBlockEntry* entry = new(zone()) HBlockEntry();
159 entry->InitializeAsFirst(this); 156 entry->InitializeAsFirst(this);
160 if (!position.IsUnknown()) { 157 if (position != RelocInfo::kNoPosition) {
161 entry->set_position(position); 158 entry->set_position(position);
162 } else { 159 } else {
163 ASSERT(!FLAG_hydrogen_track_positions || 160 ASSERT(!FLAG_emit_opt_code_positions ||
164 !graph()->info()->IsOptimizing()); 161 !graph()->info()->IsOptimizing());
165 } 162 }
166 first_ = last_ = entry; 163 first_ = last_ = entry;
167 } 164 }
168 instr->InsertAfter(last_); 165 instr->InsertAfter(last_);
169 } 166 }
170 167
171 168
172 HPhi* HBasicBlock::AddNewPhi(int merged_index) { 169 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
173 if (graph()->IsInsideNoSideEffectsScope()) { 170 if (graph()->IsInsideNoSideEffectsScope()) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 !it.Done(); 203 !it.Done();
207 it.Advance()) { 204 it.Advance()) {
208 int index = it.Current(); 205 int index = it.Current();
209 instr->AddAssignedValue(index, environment->Lookup(index)); 206 instr->AddAssignedValue(index, environment->Lookup(index));
210 } 207 }
211 environment->ClearHistory(); 208 environment->ClearHistory();
212 return instr; 209 return instr;
213 } 210 }
214 211
215 212
216 void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) { 213 void HBasicBlock::Finish(HControlInstruction* end, int position) {
217 ASSERT(!IsFinished()); 214 ASSERT(!IsFinished());
218 AddInstruction(end, position); 215 AddInstruction(end, position);
219 end_ = end; 216 end_ = end;
220 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 217 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
221 it.Current()->RegisterPredecessor(this); 218 it.Current()->RegisterPredecessor(this);
222 } 219 }
223 } 220 }
224 221
225 222
226 void HBasicBlock::Goto(HBasicBlock* block, 223 void HBasicBlock::Goto(HBasicBlock* block,
227 HSourcePosition position, 224 int position,
228 FunctionState* state, 225 FunctionState* state,
229 bool add_simulate) { 226 bool add_simulate) {
230 bool drop_extra = state != NULL && 227 bool drop_extra = state != NULL &&
231 state->inlining_kind() == NORMAL_RETURN; 228 state->inlining_kind() == NORMAL_RETURN;
232 229
233 if (block->IsInlineReturnTarget()) { 230 if (block->IsInlineReturnTarget()) {
234 HEnvironment* env = last_environment(); 231 HEnvironment* env = last_environment();
235 int argument_count = env->arguments_environment()->parameter_count(); 232 int argument_count = env->arguments_environment()->parameter_count();
236 AddInstruction(new(zone()) 233 AddInstruction(new(zone())
237 HLeaveInlined(state->entry(), argument_count), 234 HLeaveInlined(state->entry(), argument_count),
238 position); 235 position);
239 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 236 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
240 } 237 }
241 238
242 if (add_simulate) AddNewSimulate(BailoutId::None(), position); 239 if (add_simulate) AddNewSimulate(BailoutId::None(), position);
243 HGoto* instr = new(zone()) HGoto(block); 240 HGoto* instr = new(zone()) HGoto(block);
244 Finish(instr, position); 241 Finish(instr, position);
245 } 242 }
246 243
247 244
248 void HBasicBlock::AddLeaveInlined(HValue* return_value, 245 void HBasicBlock::AddLeaveInlined(HValue* return_value,
249 FunctionState* state, 246 FunctionState* state,
250 HSourcePosition position) { 247 int position) {
251 HBasicBlock* target = state->function_return(); 248 HBasicBlock* target = state->function_return();
252 bool drop_extra = state->inlining_kind() == NORMAL_RETURN; 249 bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
253 250
254 ASSERT(target->IsInlineReturnTarget()); 251 ASSERT(target->IsInlineReturnTarget());
255 ASSERT(return_value != NULL); 252 ASSERT(return_value != NULL);
256 HEnvironment* env = last_environment(); 253 HEnvironment* env = last_environment();
257 int argument_count = env->arguments_environment()->parameter_count(); 254 int argument_count = env->arguments_environment()->parameter_count();
258 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), 255 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
259 position); 256 position);
260 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 257 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 } 330 }
334 331
335 // Only the first entry into the loop is from outside the loop. All other 332 // Only the first entry into the loop is from outside the loop. All other
336 // entries must be back edges. 333 // entries must be back edges.
337 for (int i = 1; i < predecessors()->length(); ++i) { 334 for (int i = 1; i < predecessors()->length(); ++i) {
338 loop_information()->RegisterBackEdge(predecessors()->at(i)); 335 loop_information()->RegisterBackEdge(predecessors()->at(i));
339 } 336 }
340 } 337 }
341 338
342 339
343 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
344 ASSERT(IsFinished());
345 HBasicBlock* succ_block = end()->SuccessorAt(succ);
346
347 ASSERT(succ_block->predecessors()->length() == 1);
348 succ_block->MarkUnreachable();
349 }
350
351
352 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { 340 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
353 if (HasPredecessor()) { 341 if (HasPredecessor()) {
354 // Only loop header blocks can have a predecessor added after 342 // Only loop header blocks can have a predecessor added after
355 // instructions have been added to the block (they have phis for all 343 // instructions have been added to the block (they have phis for all
356 // values in the environment, these phis may be eliminated later). 344 // values in the environment, these phis may be eliminated later).
357 ASSERT(IsLoopHeader() || first_ == NULL); 345 ASSERT(IsLoopHeader() || first_ == NULL);
358 HEnvironment* incoming_env = pred->last_environment(); 346 HEnvironment* incoming_env = pred->last_environment();
359 if (IsLoopHeader()) { 347 if (IsLoopHeader()) {
360 ASSERT(phis()->length() == incoming_env->length()); 348 ASSERT(phis()->length() == incoming_env->length());
361 for (int i = 0; i < phis_.length(); ++i) { 349 for (int i = 0; i < phis_.length(); ++i) {
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 } 1025 }
1038 builder_->GotoNoSimulate(current->block_, merge_block); 1026 builder_->GotoNoSimulate(current->block_, merge_block);
1039 } 1027 }
1040 current = current->next_; 1028 current = current->next_;
1041 } 1029 }
1042 1030
1043 // Merge deopt blocks, padding when necessary. 1031 // Merge deopt blocks, padding when necessary.
1044 current = merge_at_join_blocks_; 1032 current = merge_at_join_blocks_;
1045 while (current != NULL) { 1033 while (current != NULL) {
1046 if (current->deopt_ && current->block_ != NULL) { 1034 if (current->deopt_ && current->block_ != NULL) {
1047 current->block_->FinishExit( 1035 builder_->PadEnvironmentForContinuation(current->block_,
1048 HAbnormalExit::New(builder_->zone(), NULL), 1036 merge_block);
1049 HSourcePosition::Unknown()); 1037 builder_->GotoNoSimulate(current->block_, merge_block);
1050 } 1038 }
1051 current = current->next_; 1039 current = current->next_;
1052 } 1040 }
1053 builder_->set_current_block(merge_block); 1041 builder_->set_current_block(merge_block);
1054 } 1042 }
1055 1043
1056 1044
1057 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 1045 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
1058 HValue* context, 1046 HValue* context,
1059 LoopBuilder::Direction direction) 1047 LoopBuilder::Direction direction)
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 CompilationPhase phase("H_Block building", info_); 1160 CompilationPhase phase("H_Block building", info_);
1173 set_current_block(graph()->entry_block()); 1161 set_current_block(graph()->entry_block());
1174 if (!BuildGraph()) return NULL; 1162 if (!BuildGraph()) return NULL;
1175 graph()->FinalizeUniqueness(); 1163 graph()->FinalizeUniqueness();
1176 return graph_; 1164 return graph_;
1177 } 1165 }
1178 1166
1179 1167
1180 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 1168 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
1181 ASSERT(current_block() != NULL); 1169 ASSERT(current_block() != NULL);
1182 ASSERT(!FLAG_hydrogen_track_positions || 1170 ASSERT(!FLAG_emit_opt_code_positions ||
1183 !position_.IsUnknown() || 1171 position_ != RelocInfo::kNoPosition || !info_->IsOptimizing());
1184 !info_->IsOptimizing()); 1172 current_block()->AddInstruction(instr, position_);
1185 current_block()->AddInstruction(instr, source_position());
1186 if (graph()->IsInsideNoSideEffectsScope()) { 1173 if (graph()->IsInsideNoSideEffectsScope()) {
1187 instr->SetFlag(HValue::kHasNoObservableSideEffects); 1174 instr->SetFlag(HValue::kHasNoObservableSideEffects);
1188 } 1175 }
1189 return instr; 1176 return instr;
1190 } 1177 }
1191 1178
1192 1179
1193 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { 1180 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
1194 ASSERT(!FLAG_hydrogen_track_positions || 1181 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() ||
1195 !info_->IsOptimizing() || 1182 position_ != RelocInfo::kNoPosition);
1196 !position_.IsUnknown()); 1183 current_block()->Finish(last, position_);
1197 current_block()->Finish(last, source_position());
1198 if (last->IsReturn() || last->IsAbnormalExit()) { 1184 if (last->IsReturn() || last->IsAbnormalExit()) {
1199 set_current_block(NULL); 1185 set_current_block(NULL);
1200 } 1186 }
1201 } 1187 }
1202 1188
1203 1189
1204 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { 1190 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
1205 ASSERT(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() || 1191 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() ||
1206 !position_.IsUnknown()); 1192 position_ != RelocInfo::kNoPosition);
1207 current_block()->FinishExit(instruction, source_position()); 1193 current_block()->FinishExit(instruction, position_);
1208 if (instruction->IsReturn() || instruction->IsAbnormalExit()) { 1194 if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1209 set_current_block(NULL); 1195 set_current_block(NULL);
1210 } 1196 }
1211 } 1197 }
1212 1198
1213 1199
1214 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { 1200 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
1215 if (FLAG_native_code_counters && counter->Enabled()) { 1201 if (FLAG_native_code_counters && counter->Enabled()) {
1216 HValue* reference = Add<HConstant>(ExternalReference(counter)); 1202 HValue* reference = Add<HConstant>(ExternalReference(counter));
1217 HValue* old_value = Add<HLoadNamedField>( 1203 HValue* old_value = Add<HLoadNamedField>(
1218 reference, static_cast<HValue*>(NULL), HObjectAccess::ForCounter()); 1204 reference, static_cast<HValue*>(NULL), HObjectAccess::ForCounter());
1219 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1()); 1205 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
1220 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow 1206 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow
1221 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), 1207 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1222 new_value, STORE_TO_INITIALIZED_ENTRY); 1208 new_value, STORE_TO_INITIALIZED_ENTRY);
1223 } 1209 }
1224 } 1210 }
1225 1211
1226 1212
1227 void HGraphBuilder::AddSimulate(BailoutId id, 1213 void HGraphBuilder::AddSimulate(BailoutId id,
1228 RemovableSimulate removable) { 1214 RemovableSimulate removable) {
1229 ASSERT(current_block() != NULL); 1215 ASSERT(current_block() != NULL);
1230 ASSERT(!graph()->IsInsideNoSideEffectsScope()); 1216 ASSERT(!graph()->IsInsideNoSideEffectsScope());
1231 current_block()->AddNewSimulate(id, source_position(), removable); 1217 current_block()->AddNewSimulate(id, position_, removable);
1232 } 1218 }
1233 1219
1234 1220
1235 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 1221 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1236 HBasicBlock* b = graph()->CreateBasicBlock(); 1222 HBasicBlock* b = graph()->CreateBasicBlock();
1237 b->SetInitialEnvironment(env); 1223 b->SetInitialEnvironment(env);
1238 return b; 1224 return b;
1239 } 1225 }
1240 1226
1241 1227
1242 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 1228 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1243 HBasicBlock* header = graph()->CreateBasicBlock(); 1229 HBasicBlock* header = graph()->CreateBasicBlock();
1244 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 1230 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1245 header->SetInitialEnvironment(entry_env); 1231 header->SetInitialEnvironment(entry_env);
1246 header->AttachLoopInformation(); 1232 header->AttachLoopInformation();
1247 return header; 1233 return header;
1248 } 1234 }
1249 1235
1250 1236
1251 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { 1237 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
1252 if (obj->type().IsHeapObject()) return obj; 1238 if (obj->type().IsHeapObject()) return obj;
1253 return Add<HCheckHeapObject>(obj); 1239 return Add<HCheckHeapObject>(obj);
1254 } 1240 }
1255 1241
1256 1242
1257 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) { 1243 void HGraphBuilder::FinishExitWithHardDeoptimization(
1244 const char* reason, HBasicBlock* continuation) {
1245 PadEnvironmentForContinuation(current_block(), continuation);
1258 Add<HDeoptimize>(reason, Deoptimizer::EAGER); 1246 Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1259 FinishExitCurrentBlock(New<HAbnormalExit>()); 1247 if (graph()->IsInsideNoSideEffectsScope()) {
1248 GotoNoSimulate(continuation);
1249 } else {
1250 Goto(continuation);
1251 }
1260 } 1252 }
1261 1253
1262 1254
1255 void HGraphBuilder::PadEnvironmentForContinuation(
1256 HBasicBlock* from,
1257 HBasicBlock* continuation) {
1258 if (continuation->last_environment() != NULL) {
1259 // When merging from a deopt block to a continuation, resolve differences in
1260 // environment by pushing constant 0 and popping extra values so that the
1261 // environments match during the join. Push 0 since it has the most specific
1262 // representation, and will not influence representation inference of the
1263 // phi.
1264 int continuation_env_length = continuation->last_environment()->length();
1265 while (continuation_env_length != from->last_environment()->length()) {
1266 if (continuation_env_length > from->last_environment()->length()) {
1267 from->last_environment()->Push(graph()->GetConstant0());
1268 } else {
1269 from->last_environment()->Pop();
1270 }
1271 }
1272 } else {
1273 ASSERT(continuation->predecessors()->length() == 0);
1274 }
1275 }
1276
1277
1263 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { 1278 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) {
1264 return Add<HCheckMaps>(obj, map, top_info()); 1279 return Add<HCheckMaps>(obj, map, top_info());
1265 } 1280 }
1266 1281
1267 1282
1268 HValue* HGraphBuilder::BuildCheckString(HValue* string) { 1283 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
1269 if (!string->type().IsString()) { 1284 if (!string->type().IsString()) {
1270 ASSERT(!string->IsConstant() || 1285 ASSERT(!string->IsConstant() ||
1271 !HConstant::cast(string)->HasStringValue()); 1286 !HConstant::cast(string)->HasStringValue());
1272 BuildCheckHeapObject(string); 1287 BuildCheckHeapObject(string);
1273 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); 1288 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1274 } 1289 }
1275 return string; 1290 return string;
1276 } 1291 }
1277 1292
1278 1293
1279 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { 1294 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1280 if (object->type().IsJSObject()) return object; 1295 if (object->type().IsJSObject()) return object;
1281 if (function->IsConstant() && 1296 if (function->IsConstant() &&
1282 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { 1297 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
1283 Handle<JSFunction> f = Handle<JSFunction>::cast( 1298 Handle<JSFunction> f = Handle<JSFunction>::cast(
1284 HConstant::cast(function)->handle(isolate())); 1299 HConstant::cast(function)->handle(isolate()));
1285 SharedFunctionInfo* shared = f->shared(); 1300 SharedFunctionInfo* shared = f->shared();
1286 if (!shared->is_classic_mode() || shared->native()) return object; 1301 if (!shared->is_classic_mode() || shared->native()) return object;
1287 } 1302 }
1288 return Add<HWrapReceiver>(object, function); 1303 return Add<HWrapReceiver>(object, function);
1289 } 1304 }
1290 1305
1291 1306
1292 HValue* HGraphBuilder::BuildCheckForCapacityGrow( 1307 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1293 HValue* object, 1308 HValue* elements,
1294 HValue* elements, 1309 ElementsKind kind,
1295 ElementsKind kind, 1310 HValue* length,
1296 HValue* length, 1311 HValue* key,
1297 HValue* key, 1312 bool is_js_array,
1298 bool is_js_array, 1313 bool is_store) {
1299 PropertyAccessType access_type) {
1300 IfBuilder length_checker(this); 1314 IfBuilder length_checker(this);
1301 1315
1302 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; 1316 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1303 length_checker.If<HCompareNumericAndBranch>(key, length, token); 1317 length_checker.If<HCompareNumericAndBranch>(key, length, token);
1304 1318
1305 length_checker.Then(); 1319 length_checker.Then();
1306 1320
1307 HValue* current_capacity = AddLoadFixedArrayLength(elements); 1321 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1308 1322
1309 IfBuilder capacity_checker(this); 1323 IfBuilder capacity_checker(this);
(...skipping 22 matching lines...) Expand all
1332 capacity_checker.End(); 1346 capacity_checker.End();
1333 1347
1334 if (is_js_array) { 1348 if (is_js_array) {
1335 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); 1349 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1336 new_length->ClearFlag(HValue::kCanOverflow); 1350 new_length->ClearFlag(HValue::kCanOverflow);
1337 1351
1338 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), 1352 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1339 new_length); 1353 new_length);
1340 } 1354 }
1341 1355
1342 if (access_type == STORE && kind == FAST_SMI_ELEMENTS) { 1356 if (is_store && kind == FAST_SMI_ELEMENTS) {
1343 HValue* checked_elements = environment()->Top(); 1357 HValue* checked_elements = environment()->Top();
1344 1358
1345 // Write zero to ensure that the new element is initialized with some smi. 1359 // Write zero to ensure that the new element is initialized with some smi.
1346 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind); 1360 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1347 } 1361 }
1348 1362
1349 length_checker.Else(); 1363 length_checker.Else();
1350 Add<HBoundsCheck>(key, length); 1364 Add<HBoundsCheck>(key, length);
1351 1365
1352 environment()->Push(elements); 1366 environment()->Push(elements);
1353 length_checker.End(); 1367 length_checker.End();
1354 1368
1355 return environment()->Pop(); 1369 return environment()->Pop();
1356 } 1370 }
1357 1371
1358 1372
1359 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, 1373 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1360 HValue* elements, 1374 HValue* elements,
1361 ElementsKind kind, 1375 ElementsKind kind,
1362 HValue* length) { 1376 HValue* length) {
1363 Factory* factory = isolate()->factory(); 1377 Factory* factory = isolate()->factory();
1364 1378
1365 IfBuilder cow_checker(this); 1379 IfBuilder cow_checker(this);
1366 1380
1367 cow_checker.If<HCompareMap>( 1381 cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
1368 elements, factory->fixed_cow_array_map(), top_info());
1369 cow_checker.Then(); 1382 cow_checker.Then();
1370 1383
1371 HValue* capacity = AddLoadFixedArrayLength(elements); 1384 HValue* capacity = AddLoadFixedArrayLength(elements);
1372 1385
1373 HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, 1386 HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
1374 kind, length, capacity); 1387 kind, length, capacity);
1375 1388
1376 environment()->Push(new_elements); 1389 environment()->Push(new_elements);
1377 1390
1378 cow_checker.Else(); 1391 cow_checker.Else();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 int32_t entry_size = SeededNumberDictionary::kEntrySize; 1457 int32_t entry_size = SeededNumberDictionary::kEntrySize;
1445 raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size)); 1458 raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size));
1446 raw_index->ClearFlag(HValue::kCanOverflow); 1459 raw_index->ClearFlag(HValue::kCanOverflow);
1447 1460
1448 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex; 1461 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex;
1449 HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset)); 1462 HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset));
1450 key_index->ClearFlag(HValue::kCanOverflow); 1463 key_index->ClearFlag(HValue::kCanOverflow);
1451 1464
1452 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index, 1465 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index,
1453 static_cast<HValue*>(NULL), 1466 static_cast<HValue*>(NULL),
1454 FAST_ELEMENTS); 1467 FAST_SMI_ELEMENTS);
1455 1468
1456 IfBuilder key_compare(this); 1469 IfBuilder key_compare(this);
1457 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key); 1470 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key);
1458 key_compare.Then(); 1471 key_compare.Then();
1459 { 1472 {
1460 // Key at the current probe doesn't match, try at the next probe. 1473 // Key at the current probe doesn't match, try at the next probe.
1461 HValue* result = BuildUncheckedDictionaryElementLoadHelper( 1474 HValue* result = BuildUncheckedDictionaryElementLoadHelper(
1462 elements, key, hash, mask, current_probe + 1); 1475 elements, key, hash, mask, current_probe + 1);
1463 if (result == NULL) { 1476 if (result == NULL) {
1464 key_compare.Deopt("probes exhausted in keyed load dictionary lookup"); 1477 key_compare.Deopt("probes exhausted in keyed load dictionary lookup");
1465 result = graph()->GetConstantUndefined(); 1478 result = graph()->GetConstantUndefined();
1466 } else { 1479 } else {
1467 Push(result); 1480 Push(result);
1468 } 1481 }
1469 } 1482 }
1470 key_compare.Else(); 1483 key_compare.Else();
1471 { 1484 {
1472 // Key at current probe matches. Details must be zero, otherwise the 1485 // Key at current probe matches. Details must be zero, otherwise the
1473 // dictionary element requires special handling. 1486 // dictionary element requires special handling.
1474 HValue* details_index = AddUncasted<HAdd>( 1487 HValue* details_index = AddUncasted<HAdd>(
1475 raw_index, Add<HConstant>(base_offset + 2)); 1488 raw_index, Add<HConstant>(base_offset + 2));
1476 details_index->ClearFlag(HValue::kCanOverflow); 1489 details_index->ClearFlag(HValue::kCanOverflow);
1477 1490
1478 HValue* details = Add<HLoadKeyed>(elements, details_index, 1491 HValue* details = Add<HLoadKeyed>(elements, details_index,
1479 static_cast<HValue*>(NULL), 1492 static_cast<HValue*>(NULL),
1480 FAST_ELEMENTS); 1493 FAST_SMI_ELEMENTS);
1481 IfBuilder details_compare(this); 1494 IfBuilder details_compare(this);
1482 details_compare.If<HCompareNumericAndBranch>(details, 1495 details_compare.If<HCompareNumericAndBranch>(details,
1483 graph()->GetConstant0(), 1496 graph()->GetConstant0(),
1484 Token::NE); 1497 Token::NE);
1485 details_compare.ThenDeopt("keyed load dictionary element not fast case"); 1498 details_compare.ThenDeopt("keyed load dictionary element not fast case");
1486 1499
1487 details_compare.Else(); 1500 details_compare.Else();
1488 { 1501 {
1489 // Key matches and details are zero --> fast case. Load and return the 1502 // Key matches and details are zero --> fast case. Load and return the
1490 // value. 1503 // value.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1540 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, 1553 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
1541 HValue* key) { 1554 HValue* key) {
1542 HValue* elements = AddLoadElements(receiver); 1555 HValue* elements = AddLoadElements(receiver);
1543 1556
1544 HValue* hash = BuildElementIndexHash(key); 1557 HValue* hash = BuildElementIndexHash(key);
1545 1558
1546 HValue* capacity = Add<HLoadKeyed>( 1559 HValue* capacity = Add<HLoadKeyed>(
1547 elements, 1560 elements,
1548 Add<HConstant>(NameDictionary::kCapacityIndex), 1561 Add<HConstant>(NameDictionary::kCapacityIndex),
1549 static_cast<HValue*>(NULL), 1562 static_cast<HValue*>(NULL),
1550 FAST_ELEMENTS); 1563 FAST_SMI_ELEMENTS);
1551 1564
1552 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); 1565 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
1553 mask->ChangeRepresentation(Representation::Integer32()); 1566 mask->ChangeRepresentation(Representation::Integer32());
1554 mask->ClearFlag(HValue::kCanOverflow); 1567 mask->ClearFlag(HValue::kCanOverflow);
1555 1568
1556 return BuildUncheckedDictionaryElementLoadHelper(elements, key, 1569 return BuildUncheckedDictionaryElementLoadHelper(elements, key,
1557 hash, mask, 0); 1570 hash, mask, 0);
1558 } 1571 }
1559 1572
1560 1573
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 if_objectiskey.JoinContinuation(&found); 1688 if_objectiskey.JoinContinuation(&found);
1676 } 1689 }
1677 if_objectissmi.Else(); 1690 if_objectissmi.Else();
1678 { 1691 {
1679 if (type->Is(Type::Smi())) { 1692 if (type->Is(Type::Smi())) {
1680 if_objectissmi.Deopt("Expected smi"); 1693 if_objectissmi.Deopt("Expected smi");
1681 } else { 1694 } else {
1682 // Check if the object is a heap number. 1695 // Check if the object is a heap number.
1683 IfBuilder if_objectisnumber(this); 1696 IfBuilder if_objectisnumber(this);
1684 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>( 1697 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
1685 object, isolate()->factory()->heap_number_map(), top_info()); 1698 object, isolate()->factory()->heap_number_map());
1686 if_objectisnumber.Then(); 1699 if_objectisnumber.Then();
1687 { 1700 {
1688 // Compute hash for heap number similar to double_get_hash(). 1701 // Compute hash for heap number similar to double_get_hash().
1689 HValue* low = Add<HLoadNamedField>( 1702 HValue* low = Add<HLoadNamedField>(
1690 object, objectisnumber, 1703 object, objectisnumber,
1691 HObjectAccess::ForHeapNumberValueLowestBits()); 1704 HObjectAccess::ForHeapNumberValueLowestBits());
1692 HValue* high = Add<HLoadNamedField>( 1705 HValue* high = Add<HLoadNamedField>(
1693 object, objectisnumber, 1706 object, objectisnumber,
1694 HObjectAccess::ForHeapNumberValueHighestBits()); 1707 HObjectAccess::ForHeapNumberValueHighestBits());
1695 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high); 1708 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
2139 return Pop(); 2152 return Pop();
2140 } 2153 }
2141 2154
2142 2155
2143 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 2156 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
2144 HValue* checked_object, 2157 HValue* checked_object,
2145 HValue* key, 2158 HValue* key,
2146 HValue* val, 2159 HValue* val,
2147 bool is_js_array, 2160 bool is_js_array,
2148 ElementsKind elements_kind, 2161 ElementsKind elements_kind,
2149 PropertyAccessType access_type, 2162 bool is_store,
2150 LoadKeyedHoleMode load_mode, 2163 LoadKeyedHoleMode load_mode,
2151 KeyedAccessStoreMode store_mode) { 2164 KeyedAccessStoreMode store_mode) {
2152 ASSERT((!IsExternalArrayElementsKind(elements_kind) && 2165 ASSERT((!IsExternalArrayElementsKind(elements_kind) &&
2153 !IsFixedTypedArrayElementsKind(elements_kind)) || 2166 !IsFixedTypedArrayElementsKind(elements_kind)) ||
2154 !is_js_array); 2167 !is_js_array);
2155 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 2168 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
2156 // on a HElementsTransition instruction. The flag can also be removed if the 2169 // on a HElementsTransition instruction. The flag can also be removed if the
2157 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 2170 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
2158 // ElementsKind transitions. Finally, the dependency can be removed for stores 2171 // ElementsKind transitions. Finally, the dependency can be removed for stores
2159 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 2172 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
2160 // generated store code. 2173 // generated store code.
2161 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 2174 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
2162 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { 2175 (elements_kind == FAST_ELEMENTS && is_store)) {
2163 checked_object->ClearDependsOnFlag(kElementsKind); 2176 checked_object->ClearGVNFlag(kDependsOnElementsKind);
2164 } 2177 }
2165 2178
2166 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 2179 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
2167 bool fast_elements = IsFastObjectElementsKind(elements_kind); 2180 bool fast_elements = IsFastObjectElementsKind(elements_kind);
2168 HValue* elements = AddLoadElements(checked_object); 2181 HValue* elements = AddLoadElements(checked_object);
2169 if (access_type == STORE && (fast_elements || fast_smi_only_elements) && 2182 if (is_store && (fast_elements || fast_smi_only_elements) &&
2170 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 2183 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
2171 HCheckMaps* check_cow_map = Add<HCheckMaps>( 2184 HCheckMaps* check_cow_map = Add<HCheckMaps>(
2172 elements, isolate()->factory()->fixed_array_map(), top_info()); 2185 elements, isolate()->factory()->fixed_array_map(), top_info());
2173 check_cow_map->ClearDependsOnFlag(kElementsKind); 2186 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
2174 } 2187 }
2175 HInstruction* length = NULL; 2188 HInstruction* length = NULL;
2176 if (is_js_array) { 2189 if (is_js_array) {
2177 length = Add<HLoadNamedField>( 2190 length = Add<HLoadNamedField>(
2178 checked_object, static_cast<HValue*>(NULL), 2191 checked_object, static_cast<HValue*>(NULL),
2179 HObjectAccess::ForArrayLength(elements_kind)); 2192 HObjectAccess::ForArrayLength(elements_kind));
2180 } else { 2193 } else {
2181 length = AddLoadFixedArrayLength(elements); 2194 length = AddLoadFixedArrayLength(elements);
2182 } 2195 }
2183 length->set_type(HType::Smi()); 2196 length->set_type(HType::Smi());
(...skipping 11 matching lines...) Expand all
2195 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 2208 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2196 NoObservableSideEffectsScope no_effects(this); 2209 NoObservableSideEffectsScope no_effects(this);
2197 IfBuilder length_checker(this); 2210 IfBuilder length_checker(this);
2198 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 2211 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
2199 length_checker.Then(); 2212 length_checker.Then();
2200 IfBuilder negative_checker(this); 2213 IfBuilder negative_checker(this);
2201 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 2214 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
2202 key, graph()->GetConstant0(), Token::GTE); 2215 key, graph()->GetConstant0(), Token::GTE);
2203 negative_checker.Then(); 2216 negative_checker.Then();
2204 HInstruction* result = AddElementAccess( 2217 HInstruction* result = AddElementAccess(
2205 backing_store, key, val, bounds_check, elements_kind, access_type); 2218 backing_store, key, val, bounds_check, elements_kind, is_store);
2206 negative_checker.ElseDeopt("Negative key encountered"); 2219 negative_checker.ElseDeopt("Negative key encountered");
2207 negative_checker.End(); 2220 negative_checker.End();
2208 length_checker.End(); 2221 length_checker.End();
2209 return result; 2222 return result;
2210 } else { 2223 } else {
2211 ASSERT(store_mode == STANDARD_STORE); 2224 ASSERT(store_mode == STANDARD_STORE);
2212 checked_key = Add<HBoundsCheck>(key, length); 2225 checked_key = Add<HBoundsCheck>(key, length);
2213 return AddElementAccess( 2226 return AddElementAccess(
2214 backing_store, checked_key, val, 2227 backing_store, checked_key, val,
2215 checked_object, elements_kind, access_type); 2228 checked_object, elements_kind, is_store);
2216 } 2229 }
2217 } 2230 }
2218 ASSERT(fast_smi_only_elements || 2231 ASSERT(fast_smi_only_elements ||
2219 fast_elements || 2232 fast_elements ||
2220 IsFastDoubleElementsKind(elements_kind)); 2233 IsFastDoubleElementsKind(elements_kind));
2221 2234
2222 // In case val is stored into a fast smi array, assure that the value is a smi 2235 // In case val is stored into a fast smi array, assure that the value is a smi
2223 // before manipulating the backing store. Otherwise the actual store may 2236 // before manipulating the backing store. Otherwise the actual store may
2224 // deopt, leaving the backing store in an invalid state. 2237 // deopt, leaving the backing store in an invalid state.
2225 if (access_type == STORE && IsFastSmiElementsKind(elements_kind) && 2238 if (is_store && IsFastSmiElementsKind(elements_kind) &&
2226 !val->type().IsSmi()) { 2239 !val->type().IsSmi()) {
2227 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); 2240 val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2228 } 2241 }
2229 2242
2230 if (IsGrowStoreMode(store_mode)) { 2243 if (IsGrowStoreMode(store_mode)) {
2231 NoObservableSideEffectsScope no_effects(this); 2244 NoObservableSideEffectsScope no_effects(this);
2232 elements = BuildCheckForCapacityGrow(checked_object, elements, 2245 elements = BuildCheckForCapacityGrow(checked_object, elements,
2233 elements_kind, length, key, 2246 elements_kind, length, key,
2234 is_js_array, access_type); 2247 is_js_array, is_store);
2235 checked_key = key; 2248 checked_key = key;
2236 } else { 2249 } else {
2237 checked_key = Add<HBoundsCheck>(key, length); 2250 checked_key = Add<HBoundsCheck>(key, length);
2238 2251
2239 if (access_type == STORE && (fast_elements || fast_smi_only_elements)) { 2252 if (is_store && (fast_elements || fast_smi_only_elements)) {
2240 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 2253 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2241 NoObservableSideEffectsScope no_effects(this); 2254 NoObservableSideEffectsScope no_effects(this);
2242 elements = BuildCopyElementsOnWrite(checked_object, elements, 2255 elements = BuildCopyElementsOnWrite(checked_object, elements,
2243 elements_kind, length); 2256 elements_kind, length);
2244 } else { 2257 } else {
2245 HCheckMaps* check_cow_map = Add<HCheckMaps>( 2258 HCheckMaps* check_cow_map = Add<HCheckMaps>(
2246 elements, isolate()->factory()->fixed_array_map(), top_info()); 2259 elements, isolate()->factory()->fixed_array_map(), top_info());
2247 check_cow_map->ClearDependsOnFlag(kElementsKind); 2260 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
2248 } 2261 }
2249 } 2262 }
2250 } 2263 }
2251 return AddElementAccess(elements, checked_key, val, checked_object, 2264 return AddElementAccess(elements, checked_key, val, checked_object,
2252 elements_kind, access_type, load_mode); 2265 elements_kind, is_store, load_mode);
2253 } 2266 }
2254 2267
2255 2268
2256 2269
2257 HValue* HGraphBuilder::BuildAllocateArrayFromLength( 2270 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2258 JSArrayBuilder* array_builder, 2271 JSArrayBuilder* array_builder,
2259 HValue* length_argument) { 2272 HValue* length_argument) {
2260 if (length_argument->IsConstant() && 2273 if (length_argument->IsConstant() &&
2261 HConstant::cast(length_argument)->HasSmiValue()) { 2274 HConstant::cast(length_argument)->HasSmiValue()) {
2262 int array_length = HConstant::cast(length_argument)->Integer32Value(); 2275 int array_length = HConstant::cast(length_argument)->Integer32Value();
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 return elements; 2397 return elements;
2385 } 2398 }
2386 2399
2387 2400
2388 HInstruction* HGraphBuilder::AddElementAccess( 2401 HInstruction* HGraphBuilder::AddElementAccess(
2389 HValue* elements, 2402 HValue* elements,
2390 HValue* checked_key, 2403 HValue* checked_key,
2391 HValue* val, 2404 HValue* val,
2392 HValue* dependency, 2405 HValue* dependency,
2393 ElementsKind elements_kind, 2406 ElementsKind elements_kind,
2394 PropertyAccessType access_type, 2407 bool is_store,
2395 LoadKeyedHoleMode load_mode) { 2408 LoadKeyedHoleMode load_mode) {
2396 if (access_type == STORE) { 2409 if (is_store) {
2397 ASSERT(val != NULL); 2410 ASSERT(val != NULL);
2398 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || 2411 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
2399 elements_kind == UINT8_CLAMPED_ELEMENTS) { 2412 elements_kind == UINT8_CLAMPED_ELEMENTS) {
2400 val = Add<HClampToUint8>(val); 2413 val = Add<HClampToUint8>(val);
2401 } 2414 }
2402 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, 2415 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2403 elements_kind == FAST_SMI_ELEMENTS 2416 elements_kind == FAST_SMI_ELEMENTS
2404 ? STORE_TO_INITIALIZED_ENTRY 2417 ? STORE_TO_INITIALIZED_ENTRY
2405 : INITIALIZING_STORE); 2418 : INITIALIZING_STORE);
2406 } 2419 }
2407 2420
2408 ASSERT(access_type == LOAD); 2421 ASSERT(!is_store);
2409 ASSERT(val == NULL); 2422 ASSERT(val == NULL);
2410 HLoadKeyed* load = Add<HLoadKeyed>( 2423 HLoadKeyed* load = Add<HLoadKeyed>(
2411 elements, checked_key, dependency, elements_kind, load_mode); 2424 elements, checked_key, dependency, elements_kind, load_mode);
2412 if (FLAG_opt_safe_uint32_operations && 2425 if (FLAG_opt_safe_uint32_operations &&
2413 (elements_kind == EXTERNAL_UINT32_ELEMENTS || 2426 (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
2414 elements_kind == UINT32_ELEMENTS)) { 2427 elements_kind == UINT32_ELEMENTS)) {
2415 graph()->RecordUint32Instruction(load); 2428 graph()->RecordUint32Instruction(load);
2416 } 2429 }
2417 return load; 2430 return load;
2418 } 2431 }
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
2814 // A constant map is fine. 2827 // A constant map is fine.
2815 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_), 2828 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
2816 builder()->isolate()); 2829 builder()->isolate());
2817 return builder()->Add<HConstant>(map); 2830 return builder()->Add<HConstant>(map);
2818 } 2831 }
2819 2832
2820 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) { 2833 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
2821 // No need for a context lookup if the kind_ matches the initial 2834 // No need for a context lookup if the kind_ matches the initial
2822 // map, because we can just load the map in that case. 2835 // map, because we can just load the map in that case.
2823 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2836 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2824 return builder()->Add<HLoadNamedField>( 2837 return builder()->AddLoadNamedField(constructor_function_, access);
2825 constructor_function_, static_cast<HValue*>(NULL), access);
2826 } 2838 }
2827 2839
2828 // TODO(mvstanton): we should always have a constructor function if we 2840 // TODO(mvstanton): we should always have a constructor function if we
2829 // are creating a stub. 2841 // are creating a stub.
2830 HInstruction* native_context = constructor_function_ != NULL 2842 HInstruction* native_context = constructor_function_ != NULL
2831 ? builder()->BuildGetNativeContext(constructor_function_) 2843 ? builder()->BuildGetNativeContext(constructor_function_)
2832 : builder()->BuildGetNativeContext(); 2844 : builder()->BuildGetNativeContext();
2833 2845
2834 HInstruction* index = builder()->Add<HConstant>( 2846 HInstruction* index = builder()->Add<HConstant>(
2835 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 2847 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
2836 2848
2837 HInstruction* map_array = builder()->Add<HLoadKeyed>( 2849 HInstruction* map_array = builder()->Add<HLoadKeyed>(
2838 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2850 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2839 2851
2840 HInstruction* kind_index = builder()->Add<HConstant>(kind_); 2852 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
2841 2853
2842 return builder()->Add<HLoadKeyed>( 2854 return builder()->Add<HLoadKeyed>(
2843 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2855 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2844 } 2856 }
2845 2857
2846 2858
2847 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { 2859 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
2848 // Find the map near the constructor function 2860 // Find the map near the constructor function
2849 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2861 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2850 return builder()->Add<HLoadNamedField>( 2862 return builder()->AddLoadNamedField(constructor_function_, access);
2851 constructor_function_, static_cast<HValue*>(NULL), access);
2852 } 2863 }
2853 2864
2854 2865
2855 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( 2866 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
2856 HValue* length_node) { 2867 HValue* length_node) {
2857 ASSERT(length_node != NULL); 2868 ASSERT(length_node != NULL);
2858 2869
2859 int base_size = JSArray::kSize; 2870 int base_size = JSArray::kSize;
2860 if (mode_ == TRACK_ALLOCATION_SITE) { 2871 if (mode_ == TRACK_ALLOCATION_SITE) {
2861 base_size += AllocationMemento::kSize; 2872 base_size += AllocationMemento::kSize;
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2975 HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset( 2986 HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
2976 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); 2987 JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
2977 return Add<HLoadNamedField>( 2988 return Add<HLoadNamedField>(
2978 builtins, static_cast<HValue*>(NULL), function_access); 2989 builtins, static_cast<HValue*>(NULL), function_access);
2979 } 2990 }
2980 2991
2981 2992
2982 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) 2993 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
2983 : HGraphBuilder(info), 2994 : HGraphBuilder(info),
2984 function_state_(NULL), 2995 function_state_(NULL),
2985 initial_function_state_(this, info, NORMAL_RETURN, 0), 2996 initial_function_state_(this, info, NORMAL_RETURN),
2986 ast_context_(NULL), 2997 ast_context_(NULL),
2987 break_scope_(NULL), 2998 break_scope_(NULL),
2988 inlined_count_(0), 2999 inlined_count_(0),
2989 globals_(10, info->zone()), 3000 globals_(10, info->zone()),
2990 inline_bailout_(false), 3001 inline_bailout_(false),
2991 osr_(new(info->zone()) HOsrBuilder(this)) { 3002 osr_(new(info->zone()) HOsrBuilder(this)) {
2992 // This is not initialized in the initializer list because the 3003 // This is not initialized in the initializer list because the
2993 // constructor for the initial state relies on function_state_ == NULL 3004 // constructor for the initial state relies on function_state_ == NULL
2994 // to know it's the initial state. 3005 // to know it's the initial state.
2995 function_state_= &initial_function_state_; 3006 function_state_= &initial_function_state_;
2996 InitializeAstVisitor(info->zone()); 3007 InitializeAstVisitor(info->zone());
2997 if (FLAG_hydrogen_track_positions) { 3008 if (FLAG_emit_opt_code_positions) {
2998 SetSourcePosition(info->shared_info()->start_position()); 3009 SetSourcePosition(info->shared_info()->start_position());
2999 } 3010 }
3000 } 3011 }
3001 3012
3002 3013
3003 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, 3014 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
3004 HBasicBlock* second, 3015 HBasicBlock* second,
3005 BailoutId join_id) { 3016 BailoutId join_id) {
3006 if (first == NULL) { 3017 if (first == NULL) {
3007 return second; 3018 return second;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3056 3067
3057 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( 3068 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
3058 IterationStatement* statement) { 3069 IterationStatement* statement) {
3059 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) 3070 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
3060 ? osr()->BuildOsrLoopEntry(statement) 3071 ? osr()->BuildOsrLoopEntry(statement)
3061 : BuildLoopEntry(); 3072 : BuildLoopEntry();
3062 return loop_entry; 3073 return loop_entry;
3063 } 3074 }
3064 3075
3065 3076
3066 void HBasicBlock::FinishExit(HControlInstruction* instruction, 3077 void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) {
3067 HSourcePosition position) {
3068 Finish(instruction, position); 3078 Finish(instruction, position);
3069 ClearEnvironment(); 3079 ClearEnvironment();
3070 } 3080 }
3071 3081
3072 3082
3073 HGraph::HGraph(CompilationInfo* info) 3083 HGraph::HGraph(CompilationInfo* info)
3074 : isolate_(info->isolate()), 3084 : isolate_(info->isolate()),
3075 next_block_id_(0), 3085 next_block_id_(0),
3076 entry_block_(NULL), 3086 entry_block_(NULL),
3077 blocks_(8, info->zone()), 3087 blocks_(8, info->zone()),
3078 values_(16, info->zone()), 3088 values_(16, info->zone()),
3079 phi_list_(NULL), 3089 phi_list_(NULL),
3080 uint32_instructions_(NULL), 3090 uint32_instructions_(NULL),
3081 osr_(NULL), 3091 osr_(NULL),
3082 info_(info), 3092 info_(info),
3083 zone_(info->zone()), 3093 zone_(info->zone()),
3084 is_recursive_(false), 3094 is_recursive_(false),
3085 use_optimistic_licm_(false), 3095 use_optimistic_licm_(false),
3086 depends_on_empty_array_proto_elements_(false), 3096 depends_on_empty_array_proto_elements_(false),
3087 type_change_checksum_(0), 3097 type_change_checksum_(0),
3088 maximum_environment_size_(0), 3098 maximum_environment_size_(0),
3089 no_side_effects_scope_count_(0), 3099 no_side_effects_scope_count_(0),
3090 disallow_adding_new_values_(false), 3100 disallow_adding_new_values_(false) {
3091 next_inline_id_(0),
3092 inlined_functions_(5, info->zone()) {
3093 if (info->IsStub()) { 3101 if (info->IsStub()) {
3094 HydrogenCodeStub* stub = info->code_stub(); 3102 HydrogenCodeStub* stub = info->code_stub();
3095 CodeStubInterfaceDescriptor* descriptor = 3103 CodeStubInterfaceDescriptor* descriptor =
3096 stub->GetInterfaceDescriptor(isolate_); 3104 stub->GetInterfaceDescriptor(isolate_);
3097 start_environment_ = 3105 start_environment_ =
3098 new(zone_) HEnvironment(zone_, descriptor->environment_length()); 3106 new(zone_) HEnvironment(zone_, descriptor->environment_length());
3099 } else { 3107 } else {
3100 TraceInlinedFunction(info->shared_info(), HSourcePosition::Unknown());
3101 start_environment_ = 3108 start_environment_ =
3102 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 3109 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
3103 } 3110 }
3104 start_environment_->set_ast_id(BailoutId::FunctionEntry()); 3111 start_environment_->set_ast_id(BailoutId::FunctionEntry());
3105 entry_block_ = CreateBasicBlock(); 3112 entry_block_ = CreateBasicBlock();
3106 entry_block_->SetInitialEnvironment(start_environment_); 3113 entry_block_->SetInitialEnvironment(start_environment_);
3107 } 3114 }
3108 3115
3109 3116
3110 HBasicBlock* HGraph::CreateBasicBlock() { 3117 HBasicBlock* HGraph::CreateBasicBlock() {
3111 HBasicBlock* result = new(zone()) HBasicBlock(this); 3118 HBasicBlock* result = new(zone()) HBasicBlock(this);
3112 blocks_.Add(result, zone()); 3119 blocks_.Add(result, zone());
3113 return result; 3120 return result;
3114 } 3121 }
3115 3122
3116 3123
3117 void HGraph::FinalizeUniqueness() { 3124 void HGraph::FinalizeUniqueness() {
3118 DisallowHeapAllocation no_gc; 3125 DisallowHeapAllocation no_gc;
3119 ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate())); 3126 ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
3120 for (int i = 0; i < blocks()->length(); ++i) { 3127 for (int i = 0; i < blocks()->length(); ++i) {
3121 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { 3128 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
3122 it.Current()->FinalizeUniqueness(); 3129 it.Current()->FinalizeUniqueness();
3123 } 3130 }
3124 } 3131 }
3125 } 3132 }
3126 3133
3127 3134
3128 int HGraph::TraceInlinedFunction(
3129 Handle<SharedFunctionInfo> shared,
3130 HSourcePosition position) {
3131 if (!FLAG_hydrogen_track_positions) {
3132 return 0;
3133 }
3134
3135 int id = 0;
3136 for (; id < inlined_functions_.length(); id++) {
3137 if (inlined_functions_[id].shared().is_identical_to(shared)) {
3138 break;
3139 }
3140 }
3141
3142 if (id == inlined_functions_.length()) {
3143 inlined_functions_.Add(InlinedFunctionInfo(shared), zone());
3144
3145 if (!shared->script()->IsUndefined()) {
3146 Handle<Script> script(Script::cast(shared->script()));
3147 if (!script->source()->IsUndefined()) {
3148 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
3149 PrintF(tracing_scope.file(),
3150 "--- FUNCTION SOURCE (%s) id{%d,%d} ---\n",
3151 shared->DebugName()->ToCString().get(),
3152 info()->optimization_id(),
3153 id);
3154
3155 {
3156 ConsStringIteratorOp op;
3157 StringCharacterStream stream(String::cast(script->source()),
3158 &op,
3159 shared->start_position());
3160 // fun->end_position() points to the last character in the stream. We
3161 // need to compensate by adding one to calculate the length.
3162 int source_len =
3163 shared->end_position() - shared->start_position() + 1;
3164 for (int i = 0; i < source_len; i++) {
3165 if (stream.HasMore()) {
3166 PrintF(tracing_scope.file(), "%c", stream.GetNext());
3167 }
3168 }
3169 }
3170
3171 PrintF(tracing_scope.file(), "\n--- END ---\n");
3172 }
3173 }
3174 }
3175
3176 int inline_id = next_inline_id_++;
3177
3178 if (inline_id != 0) {
3179 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
3180 PrintF(tracing_scope.file(), "INLINE (%s) id{%d,%d} AS %d AT ",
3181 shared->DebugName()->ToCString().get(),
3182 info()->optimization_id(),
3183 id,
3184 inline_id);
3185 position.PrintTo(tracing_scope.file());
3186 PrintF(tracing_scope.file(), "\n");
3187 }
3188
3189 return inline_id;
3190 }
3191
3192
3193 int HGraph::SourcePositionToScriptPosition(HSourcePosition pos) {
3194 if (!FLAG_hydrogen_track_positions || pos.IsUnknown()) {
3195 return pos.raw();
3196 }
3197
3198 return inlined_functions_[pos.inlining_id()].start_position() +
3199 pos.position();
3200 }
3201
3202
3203 // Block ordering was implemented with two mutually recursive methods, 3135 // Block ordering was implemented with two mutually recursive methods,
3204 // HGraph::Postorder and HGraph::PostorderLoopBlocks. 3136 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
3205 // The recursion could lead to stack overflow so the algorithm has been 3137 // The recursion could lead to stack overflow so the algorithm has been
3206 // implemented iteratively. 3138 // implemented iteratively.
3207 // At a high level the algorithm looks like this: 3139 // At a high level the algorithm looks like this:
3208 // 3140 //
3209 // Postorder(block, loop_header) : { 3141 // Postorder(block, loop_header) : {
3210 // if (block has already been visited or is of another loop) return; 3142 // if (block has already been visited or is of another loop) return;
3211 // mark block as visited; 3143 // mark block as visited;
3212 // if (block is a loop header) { 3144 // if (block is a loop header) {
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
3571 phi_list_->Add(phi, zone()); 3503 phi_list_->Add(phi, zone());
3572 } 3504 }
3573 } 3505 }
3574 } 3506 }
3575 3507
3576 3508
3577 // Implementation of utility class to encapsulate the translation state for 3509 // Implementation of utility class to encapsulate the translation state for
3578 // a (possibly inlined) function. 3510 // a (possibly inlined) function.
3579 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, 3511 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
3580 CompilationInfo* info, 3512 CompilationInfo* info,
3581 InliningKind inlining_kind, 3513 InliningKind inlining_kind)
3582 int inlining_id)
3583 : owner_(owner), 3514 : owner_(owner),
3584 compilation_info_(info), 3515 compilation_info_(info),
3585 call_context_(NULL), 3516 call_context_(NULL),
3586 inlining_kind_(inlining_kind), 3517 inlining_kind_(inlining_kind),
3587 function_return_(NULL), 3518 function_return_(NULL),
3588 test_context_(NULL), 3519 test_context_(NULL),
3589 entry_(NULL), 3520 entry_(NULL),
3590 arguments_object_(NULL), 3521 arguments_object_(NULL),
3591 arguments_elements_(NULL), 3522 arguments_elements_(NULL),
3592 inlining_id_(inlining_id),
3593 outer_source_position_(HSourcePosition::Unknown()),
3594 outer_(owner->function_state()) { 3523 outer_(owner->function_state()) {
3595 if (outer_ != NULL) { 3524 if (outer_ != NULL) {
3596 // State for an inline function. 3525 // State for an inline function.
3597 if (owner->ast_context()->IsTest()) { 3526 if (owner->ast_context()->IsTest()) {
3598 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 3527 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
3599 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 3528 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
3600 if_true->MarkAsInlineReturnTarget(owner->current_block()); 3529 if_true->MarkAsInlineReturnTarget(owner->current_block());
3601 if_false->MarkAsInlineReturnTarget(owner->current_block()); 3530 if_false->MarkAsInlineReturnTarget(owner->current_block());
3602 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); 3531 TestContext* outer_test_context = TestContext::cast(owner->ast_context());
3603 Expression* cond = outer_test_context->condition(); 3532 Expression* cond = outer_test_context->condition();
3604 // The AstContext constructor pushed on the context stack. This newed 3533 // The AstContext constructor pushed on the context stack. This newed
3605 // instance is the reason that AstContext can't be BASE_EMBEDDED. 3534 // instance is the reason that AstContext can't be BASE_EMBEDDED.
3606 test_context_ = new TestContext(owner, cond, if_true, if_false); 3535 test_context_ = new TestContext(owner, cond, if_true, if_false);
3607 } else { 3536 } else {
3608 function_return_ = owner->graph()->CreateBasicBlock(); 3537 function_return_ = owner->graph()->CreateBasicBlock();
3609 function_return()->MarkAsInlineReturnTarget(owner->current_block()); 3538 function_return()->MarkAsInlineReturnTarget(owner->current_block());
3610 } 3539 }
3611 // Set this after possibly allocating a new TestContext above. 3540 // Set this after possibly allocating a new TestContext above.
3612 call_context_ = owner->ast_context(); 3541 call_context_ = owner->ast_context();
3613 } 3542 }
3614 3543
3615 // Push on the state stack. 3544 // Push on the state stack.
3616 owner->set_function_state(this); 3545 owner->set_function_state(this);
3617
3618 if (FLAG_hydrogen_track_positions) {
3619 outer_source_position_ = owner->source_position();
3620 owner->EnterInlinedSource(
3621 info->shared_info()->start_position(),
3622 inlining_id);
3623 owner->SetSourcePosition(info->shared_info()->start_position());
3624 }
3625 } 3546 }
3626 3547
3627 3548
3628 FunctionState::~FunctionState() { 3549 FunctionState::~FunctionState() {
3629 delete test_context_; 3550 delete test_context_;
3630 owner_->set_function_state(outer_); 3551 owner_->set_function_state(outer_);
3631
3632 if (FLAG_hydrogen_track_positions) {
3633 owner_->set_source_position(outer_source_position_);
3634 owner_->EnterInlinedSource(
3635 outer_->compilation_info()->shared_info()->start_position(),
3636 outer_->inlining_id());
3637 }
3638 } 3552 }
3639 3553
3640 3554
3641 // Implementation of utility classes to represent an expression's context in 3555 // Implementation of utility classes to represent an expression's context in
3642 // the AST. 3556 // the AST.
3643 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind) 3557 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
3644 : owner_(owner), 3558 : owner_(owner),
3645 kind_(kind), 3559 kind_(kind),
3646 outer_(owner->ast_context()), 3560 outer_(owner->ast_context()),
3647 for_typeof_(false) { 3561 for_typeof_(false) {
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after
4440 } 4354 }
4441 4355
4442 // Generate a compare and branch. 4356 // Generate a compare and branch.
4443 CHECK_ALIVE(VisitForValue(clause->label())); 4357 CHECK_ALIVE(VisitForValue(clause->label()));
4444 HValue* label_value = Pop(); 4358 HValue* label_value = Pop();
4445 4359
4446 Type* label_type = clause->label()->bounds().lower; 4360 Type* label_type = clause->label()->bounds().lower;
4447 Type* combined_type = clause->compare_type(); 4361 Type* combined_type = clause->compare_type();
4448 HControlInstruction* compare = BuildCompareInstruction( 4362 HControlInstruction* compare = BuildCompareInstruction(
4449 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type, 4363 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
4450 combined_type, 4364 combined_type, stmt->tag()->position(), clause->label()->position(),
4451 ScriptPositionToSourcePosition(stmt->tag()->position()), 4365 clause->id());
4452 ScriptPositionToSourcePosition(clause->label()->position()),
4453 PUSH_BEFORE_SIMULATE, clause->id());
4454 4366
4455 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 4367 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4456 HBasicBlock* body_block = graph()->CreateBasicBlock(); 4368 HBasicBlock* body_block = graph()->CreateBasicBlock();
4457 body_blocks.Add(body_block, zone()); 4369 body_blocks.Add(body_block, zone());
4458 compare->SetSuccessorAt(0, body_block); 4370 compare->SetSuccessorAt(0, body_block);
4459 compare->SetSuccessorAt(1, next_test_block); 4371 compare->SetSuccessorAt(1, next_test_block);
4460 FinishCurrentBlock(compare); 4372 FinishCurrentBlock(compare);
4461 4373
4462 set_current_block(body_block); 4374 set_current_block(body_block);
4463 Drop(1); // tag_value 4375 Drop(1); // tag_value
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
4863 set_current_block(join); 4775 set_current_block(join);
4864 if (join != NULL && !ast_context()->IsEffect()) { 4776 if (join != NULL && !ast_context()->IsEffect()) {
4865 return ast_context()->ReturnValue(Pop()); 4777 return ast_context()->ReturnValue(Pop());
4866 } 4778 }
4867 } 4779 }
4868 } 4780 }
4869 4781
4870 4782
4871 HOptimizedGraphBuilder::GlobalPropertyAccess 4783 HOptimizedGraphBuilder::GlobalPropertyAccess
4872 HOptimizedGraphBuilder::LookupGlobalProperty( 4784 HOptimizedGraphBuilder::LookupGlobalProperty(
4873 Variable* var, LookupResult* lookup, PropertyAccessType access_type) { 4785 Variable* var, LookupResult* lookup, bool is_store) {
4874 if (var->is_this() || !current_info()->has_global_object()) { 4786 if (var->is_this() || !current_info()->has_global_object()) {
4875 return kUseGeneric; 4787 return kUseGeneric;
4876 } 4788 }
4877 Handle<GlobalObject> global(current_info()->global_object()); 4789 Handle<GlobalObject> global(current_info()->global_object());
4878 global->Lookup(*var->name(), lookup); 4790 global->Lookup(*var->name(), lookup);
4879 if (!lookup->IsNormal() || 4791 if (!lookup->IsNormal() ||
4880 (access_type == STORE && lookup->IsReadOnly()) || 4792 (is_store && lookup->IsReadOnly()) ||
4881 lookup->holder() != *global) { 4793 lookup->holder() != *global) {
4882 return kUseGeneric; 4794 return kUseGeneric;
4883 } 4795 }
4884 4796
4885 return kUseCell; 4797 return kUseCell;
4886 } 4798 }
4887 4799
4888 4800
4889 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { 4801 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
4890 ASSERT(var->IsContextSlot()); 4802 ASSERT(var->IsContextSlot());
4891 HValue* context = environment()->context(); 4803 HValue* context = environment()->context();
4892 int length = current_info()->scope()->ContextChainLength(var->scope()); 4804 int length = current_info()->scope()->ContextChainLength(var->scope());
4893 while (length-- > 0) { 4805 while (length-- > 0) {
4894 context = Add<HLoadNamedField>( 4806 context = AddLoadNamedField(
4895 context, static_cast<HValue*>(NULL), 4807 context, HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4896 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4897 } 4808 }
4898 return context; 4809 return context;
4899 } 4810 }
4900 4811
4901 4812
4902 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 4813 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
4903 if (expr->is_this()) { 4814 if (expr->is_this()) {
4904 current_info()->set_this_has_uses(true); 4815 current_info()->set_this_has_uses(true);
4905 } 4816 }
4906 4817
(...skipping 10 matching lines...) Expand all
4917 // Handle known global constants like 'undefined' specially to avoid a 4828 // Handle known global constants like 'undefined' specially to avoid a
4918 // load from a global cell for them. 4829 // load from a global cell for them.
4919 Handle<Object> constant_value = 4830 Handle<Object> constant_value =
4920 isolate()->factory()->GlobalConstantFor(variable->name()); 4831 isolate()->factory()->GlobalConstantFor(variable->name());
4921 if (!constant_value.is_null()) { 4832 if (!constant_value.is_null()) {
4922 HConstant* instr = New<HConstant>(constant_value); 4833 HConstant* instr = New<HConstant>(constant_value);
4923 return ast_context()->ReturnInstruction(instr, expr->id()); 4834 return ast_context()->ReturnInstruction(instr, expr->id());
4924 } 4835 }
4925 4836
4926 LookupResult lookup(isolate()); 4837 LookupResult lookup(isolate());
4927 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, LOAD); 4838 GlobalPropertyAccess type =
4839 LookupGlobalProperty(variable, &lookup, false);
4928 4840
4929 if (type == kUseCell && 4841 if (type == kUseCell &&
4930 current_info()->global_object()->IsAccessCheckNeeded()) { 4842 current_info()->global_object()->IsAccessCheckNeeded()) {
4931 type = kUseGeneric; 4843 type = kUseGeneric;
4932 } 4844 }
4933 4845
4934 if (type == kUseCell) { 4846 if (type == kUseCell) {
4935 Handle<GlobalObject> global(current_info()->global_object()); 4847 Handle<GlobalObject> global(current_info()->global_object());
4936 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 4848 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
4937 if (cell->type()->IsConstant()) { 4849 if (cell->type()->IsConstant()) {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
5152 case ObjectLiteral::Property::COMPUTED: 5064 case ObjectLiteral::Property::COMPUTED:
5153 if (key->value()->IsInternalizedString()) { 5065 if (key->value()->IsInternalizedString()) {
5154 if (property->emit_store()) { 5066 if (property->emit_store()) {
5155 CHECK_ALIVE(VisitForValue(value)); 5067 CHECK_ALIVE(VisitForValue(value));
5156 HValue* value = Pop(); 5068 HValue* value = Pop();
5157 Handle<Map> map = property->GetReceiverType(); 5069 Handle<Map> map = property->GetReceiverType();
5158 Handle<String> name = property->key()->AsPropertyName(); 5070 Handle<String> name = property->key()->AsPropertyName();
5159 HInstruction* store; 5071 HInstruction* store;
5160 if (map.is_null()) { 5072 if (map.is_null()) {
5161 // If we don't know the monomorphic type, do a generic store. 5073 // If we don't know the monomorphic type, do a generic store.
5162 CHECK_ALIVE(store = BuildNamedGeneric( 5074 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value));
5163 STORE, literal, name, value));
5164 } else { 5075 } else {
5165 PropertyAccessInfo info(this, STORE, ToType(map), name); 5076 PropertyAccessInfo info(this, STORE, ToType(map), name);
5166 if (info.CanAccessMonomorphic()) { 5077 if (info.CanAccessMonomorphic()) {
5167 HValue* checked_literal = BuildCheckMap(literal, map); 5078 HValue* checked_literal = BuildCheckMap(literal, map);
5168 ASSERT(!info.lookup()->IsPropertyCallbacks()); 5079 ASSERT(!info.lookup()->IsPropertyCallbacks());
5169 store = BuildMonomorphicAccess( 5080 store = BuildMonomorphicAccess(
5170 &info, literal, checked_literal, value, 5081 &info, literal, checked_literal, value,
5171 BailoutId::None(), BailoutId::None()); 5082 BailoutId::None(), BailoutId::None());
5172 } else { 5083 } else {
5173 CHECK_ALIVE(store = BuildNamedGeneric( 5084 CHECK_ALIVE(
5174 STORE, literal, name, value)); 5085 store = BuildStoreNamedGeneric(literal, name, value));
5175 } 5086 }
5176 } 5087 }
5177 AddInstruction(store); 5088 AddInstruction(store);
5178 if (store->HasObservableSideEffects()) { 5089 if (store->HasObservableSideEffects()) {
5179 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); 5090 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5180 } 5091 }
5181 } else { 5092 } else {
5182 CHECK_ALIVE(VisitForEffect(value)); 5093 CHECK_ALIVE(VisitForEffect(value));
5183 } 5094 }
5184 break; 5095 break;
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
5340 } 5251 }
5341 5252
5342 5253
5343 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, 5254 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
5344 Handle<Map> map) { 5255 Handle<Map> map) {
5345 BuildCheckHeapObject(object); 5256 BuildCheckHeapObject(object);
5346 return Add<HCheckMaps>(object, map, top_info()); 5257 return Add<HCheckMaps>(object, map, top_info());
5347 } 5258 }
5348 5259
5349 5260
5350 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
5351 PropertyAccessInfo* info,
5352 HValue* checked_object) {
5353 HObjectAccess access = info->access();
5354 if (access.representation().IsDouble()) {
5355 // Load the heap number.
5356 checked_object = Add<HLoadNamedField>(
5357 checked_object, static_cast<HValue*>(NULL),
5358 access.WithRepresentation(Representation::Tagged()));
5359 checked_object->set_type(HType::HeapNumber());
5360 // Load the double value from it.
5361 access = HObjectAccess::ForHeapNumberValue();
5362 }
5363 return New<HLoadNamedField>(
5364 checked_object, static_cast<HValue*>(NULL), access);
5365 }
5366
5367
5368 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( 5261 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
5369 PropertyAccessInfo* info, 5262 PropertyAccessInfo* info,
5370 HValue* checked_object, 5263 HValue* checked_object,
5371 HValue* value) { 5264 HValue* value) {
5372 bool transition_to_field = info->lookup()->IsTransition(); 5265 bool transition_to_field = info->lookup()->IsTransition();
5373 // TODO(verwaest): Move this logic into PropertyAccessInfo. 5266 // TODO(verwaest): Move this logic into PropertyAccessInfo.
5374 HObjectAccess field_access = HObjectAccess::ForField( 5267 HObjectAccess field_access = HObjectAccess::ForField(
5375 info->map(), info->lookup(), info->name()); 5268 info->map(), info->lookup(), info->name());
5376 5269
5377 HStoreNamedField *instr; 5270 HStoreNamedField *instr;
5378 if (field_access.representation().IsDouble()) { 5271 if (FLAG_track_double_fields && field_access.representation().IsDouble()) {
5379 HObjectAccess heap_number_access = 5272 HObjectAccess heap_number_access =
5380 field_access.WithRepresentation(Representation::Tagged()); 5273 field_access.WithRepresentation(Representation::Tagged());
5381 if (transition_to_field) { 5274 if (transition_to_field) {
5382 // The store requires a mutable HeapNumber to be allocated. 5275 // The store requires a mutable HeapNumber to be allocated.
5383 NoObservableSideEffectsScope no_side_effects(this); 5276 NoObservableSideEffectsScope no_side_effects(this);
5384 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); 5277 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
5385 5278
5386 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ? 5279 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ?
5387 isolate()->heap()->GetPretenureMode() : NOT_TENURED; 5280 isolate()->heap()->GetPretenureMode() : NOT_TENURED;
5388 5281
(...skipping 19 matching lines...) Expand all
5408 } else { 5301 } else {
5409 // This is a normal store. 5302 // This is a normal store.
5410 instr = New<HStoreNamedField>( 5303 instr = New<HStoreNamedField>(
5411 checked_object->ActualValue(), field_access, value, 5304 checked_object->ActualValue(), field_access, value,
5412 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); 5305 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
5413 } 5306 }
5414 5307
5415 if (transition_to_field) { 5308 if (transition_to_field) {
5416 HConstant* transition_constant = Add<HConstant>(info->transition()); 5309 HConstant* transition_constant = Add<HConstant>(info->transition());
5417 instr->SetTransition(transition_constant, top_info()); 5310 instr->SetTransition(transition_constant, top_info());
5418 instr->SetChangesFlag(kMaps); 5311 instr->SetGVNFlag(kChangesMaps);
5419 } 5312 }
5420 return instr; 5313 return instr;
5421 } 5314 }
5422 5315
5423 5316
5317 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric(
5318 HValue* object,
5319 Handle<String> name,
5320 HValue* value,
5321 bool is_uninitialized) {
5322 if (is_uninitialized) {
5323 Add<HDeoptimize>("Insufficient type feedback for property assignment",
5324 Deoptimizer::SOFT);
5325 }
5326
5327 return New<HStoreNamedGeneric>(
5328 object,
5329 name,
5330 value,
5331 function_strict_mode_flag());
5332 }
5333
5334
5424 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( 5335 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
5425 PropertyAccessInfo* info) { 5336 PropertyAccessInfo* info) {
5426 if (!CanInlinePropertyAccess(type_)) return false; 5337 if (!CanInlinePropertyAccess(type_)) return false;
5427 5338
5428 // Currently only handle Type::Number as a polymorphic case. 5339 // Currently only handle Type::Number as a polymorphic case.
5429 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber 5340 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5430 // instruction. 5341 // instruction.
5431 if (type_->Is(Type::Number())) return false; 5342 if (type_->Is(Type::Number())) return false;
5432 5343
5433 // Values are only compatible for monomorphic load if they all behave the same 5344 // Values are only compatible for monomorphic load if they all behave the same
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
5548 if (lookup_.IsFound()) { 5459 if (lookup_.IsFound()) {
5549 if (IsLoad()) return true; 5460 if (IsLoad()) return true;
5550 return !lookup_.IsReadOnly() && lookup_.IsCacheable(); 5461 return !lookup_.IsReadOnly() && lookup_.IsCacheable();
5551 } 5462 }
5552 if (!LookupInPrototypes()) return false; 5463 if (!LookupInPrototypes()) return false;
5553 if (IsLoad()) return true; 5464 if (IsLoad()) return true;
5554 5465
5555 if (lookup_.IsPropertyCallbacks()) return true; 5466 if (lookup_.IsPropertyCallbacks()) return true;
5556 Handle<Map> map = this->map(); 5467 Handle<Map> map = this->map();
5557 map->LookupTransition(NULL, *name_, &lookup_); 5468 map->LookupTransition(NULL, *name_, &lookup_);
5558 if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) { 5469 if (lookup_.IsTransitionToField(*map) && map->unused_property_fields() > 0) {
5470 transition_ = handle(lookup_.GetTransitionMapFromMap(*map));
5559 return true; 5471 return true;
5560 } 5472 }
5561 return false; 5473 return false;
5562 } 5474 }
5563 5475
5564 5476
5565 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( 5477 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
5566 SmallMapList* types) { 5478 SmallMapList* types) {
5567 ASSERT(type_->Is(ToType(types->first()))); 5479 ASSERT(type_->Is(ToType(types->first())));
5568 if (!CanAccessMonomorphic()) return false; 5480 if (!CanAccessMonomorphic()) return false;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
5628 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); 5540 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
5629 } 5541 }
5630 5542
5631 if (!info->lookup()->IsFound()) { 5543 if (!info->lookup()->IsFound()) {
5632 ASSERT(info->IsLoad()); 5544 ASSERT(info->IsLoad());
5633 return graph()->GetConstantUndefined(); 5545 return graph()->GetConstantUndefined();
5634 } 5546 }
5635 5547
5636 if (info->lookup()->IsField()) { 5548 if (info->lookup()->IsField()) {
5637 if (info->IsLoad()) { 5549 if (info->IsLoad()) {
5638 return BuildLoadNamedField(info, checked_holder); 5550 return BuildLoadNamedField(checked_holder, info->access());
5639 } else { 5551 } else {
5640 return BuildStoreNamedField(info, checked_object, value); 5552 return BuildStoreNamedField(info, checked_object, value);
5641 } 5553 }
5642 } 5554 }
5643 5555
5644 if (info->lookup()->IsTransition()) { 5556 if (info->lookup()->IsTransition()) {
5645 ASSERT(!info->IsLoad()); 5557 ASSERT(!info->IsLoad());
5646 return BuildStoreNamedField(info, checked_object, value); 5558 return BuildStoreNamedField(info, checked_object, value);
5647 } 5559 }
5648 5560
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
5724 5636
5725 if (count == 0) { 5637 if (count == 0) {
5726 join = graph()->CreateBasicBlock(); 5638 join = graph()->CreateBasicBlock();
5727 if (handle_smi) { 5639 if (handle_smi) {
5728 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 5640 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
5729 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 5641 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
5730 number_block = graph()->CreateBasicBlock(); 5642 number_block = graph()->CreateBasicBlock();
5731 smi_check = New<HIsSmiAndBranch>( 5643 smi_check = New<HIsSmiAndBranch>(
5732 object, empty_smi_block, not_smi_block); 5644 object, empty_smi_block, not_smi_block);
5733 FinishCurrentBlock(smi_check); 5645 FinishCurrentBlock(smi_check);
5734 GotoNoSimulate(empty_smi_block, number_block); 5646 Goto(empty_smi_block, number_block);
5735 set_current_block(not_smi_block); 5647 set_current_block(not_smi_block);
5736 } else { 5648 } else {
5737 BuildCheckHeapObject(object); 5649 BuildCheckHeapObject(object);
5738 } 5650 }
5739 } 5651 }
5740 ++count; 5652 ++count;
5741 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5653 HBasicBlock* if_true = graph()->CreateBasicBlock();
5742 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5654 HBasicBlock* if_false = graph()->CreateBasicBlock();
5743 HUnaryControlInstruction* compare; 5655 HUnaryControlInstruction* compare;
5744 5656
5745 HValue* dependency; 5657 HValue* dependency;
5746 if (info.type()->Is(Type::Number())) { 5658 if (info.type()->Is(Type::Number())) {
5747 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); 5659 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
5748 compare = New<HCompareMap>(object, heap_number_map, top_info(), 5660 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
5749 if_true, if_false);
5750 dependency = smi_check; 5661 dependency = smi_check;
5751 } else if (info.type()->Is(Type::String())) { 5662 } else if (info.type()->Is(Type::String())) {
5752 compare = New<HIsStringAndBranch>(object, if_true, if_false); 5663 compare = New<HIsStringAndBranch>(object, if_true, if_false);
5753 dependency = compare; 5664 dependency = compare;
5754 } else { 5665 } else {
5755 compare = New<HCompareMap>(object, info.map(), top_info(), 5666 compare = New<HCompareMap>(object, info.map(), if_true, if_false);
5756 if_true, if_false);
5757 dependency = compare; 5667 dependency = compare;
5758 } 5668 }
5759 FinishCurrentBlock(compare); 5669 FinishCurrentBlock(compare);
5760 5670
5761 if (info.type()->Is(Type::Number())) { 5671 if (info.type()->Is(Type::Number())) {
5762 GotoNoSimulate(if_true, number_block); 5672 Goto(if_true, number_block);
5763 if_true = number_block; 5673 if_true = number_block;
5674 number_block->SetJoinId(ast_id);
5764 } 5675 }
5765 5676
5766 set_current_block(if_true); 5677 set_current_block(if_true);
5767 5678
5768 HInstruction* access = BuildMonomorphicAccess( 5679 HInstruction* access = BuildMonomorphicAccess(
5769 &info, object, dependency, value, ast_id, 5680 &info, object, dependency, value, ast_id,
5770 return_id, FLAG_polymorphic_inlining); 5681 return_id, FLAG_polymorphic_inlining);
5771 5682
5772 HValue* result = NULL; 5683 HValue* result = NULL;
5773 switch (access_type) { 5684 switch (access_type) {
(...skipping 13 matching lines...) Expand all
5787 } 5698 }
5788 5699
5789 if (current_block() != NULL) Goto(join); 5700 if (current_block() != NULL) Goto(join);
5790 set_current_block(if_false); 5701 set_current_block(if_false);
5791 } 5702 }
5792 5703
5793 // Finish up. Unconditionally deoptimize if we've handled all the maps we 5704 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5794 // know about and do not want to handle ones we've never seen. Otherwise 5705 // know about and do not want to handle ones we've never seen. Otherwise
5795 // use a generic IC. 5706 // use a generic IC.
5796 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 5707 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5797 FinishExitWithHardDeoptimization("Uknown map in polymorphic access"); 5708 // Because the deopt may be the only path in the polymorphic load, make sure
5709 // that the environment stack matches the depth on deopt that it otherwise
5710 // would have had after a successful load.
5711 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
5712 const char* message = "";
5713 switch (access_type) {
5714 case LOAD:
5715 message = "Unknown map in polymorphic load";
5716 break;
5717 case STORE:
5718 message = "Unknown map in polymorphic store";
5719 break;
5720 }
5721 FinishExitWithHardDeoptimization(message, join);
5798 } else { 5722 } else {
5799 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value); 5723 HValue* result = NULL;
5800 AddInstruction(instr); 5724 switch (access_type) {
5801 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); 5725 case LOAD:
5726 result = Add<HLoadNamedGeneric>(object, name);
5727 break;
5728 case STORE:
5729 AddInstruction(BuildStoreNamedGeneric(object, name, value));
5730 result = value;
5731 break;
5732 }
5733 if (!ast_context()->IsEffect()) Push(result);
5802 5734
5803 if (join != NULL) { 5735 if (join != NULL) {
5804 Goto(join); 5736 Goto(join);
5805 } else { 5737 } else {
5806 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5738 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5807 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 5739 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
5808 return; 5740 return;
5809 } 5741 }
5810 } 5742 }
5811 5743
5812 ASSERT(join != NULL); 5744 ASSERT(join != NULL);
5813 if (join->HasPredecessor()) { 5745 join->SetJoinId(ast_id);
5814 join->SetJoinId(ast_id); 5746 set_current_block(join);
5815 set_current_block(join); 5747 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
5816 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
5817 } else {
5818 set_current_block(NULL);
5819 }
5820 } 5748 }
5821 5749
5822 5750
5823 static bool ComputeReceiverTypes(Expression* expr, 5751 static bool ComputeReceiverTypes(Expression* expr,
5824 HValue* receiver, 5752 HValue* receiver,
5825 SmallMapList** t, 5753 SmallMapList** t,
5826 Zone* zone) { 5754 Zone* zone) {
5827 SmallMapList* types = expr->GetReceiverTypes(); 5755 SmallMapList* types = expr->GetReceiverTypes();
5828 *t = types; 5756 *t = types;
5829 bool monomorphic = expr->IsMonomorphic(); 5757 bool monomorphic = expr->IsMonomorphic();
(...skipping 20 matching lines...) Expand all
5850 BailoutId ast_id, 5778 BailoutId ast_id,
5851 BailoutId return_id, 5779 BailoutId return_id,
5852 bool is_uninitialized) { 5780 bool is_uninitialized) {
5853 if (!prop->key()->IsPropertyName()) { 5781 if (!prop->key()->IsPropertyName()) {
5854 // Keyed store. 5782 // Keyed store.
5855 HValue* value = environment()->ExpressionStackAt(0); 5783 HValue* value = environment()->ExpressionStackAt(0);
5856 HValue* key = environment()->ExpressionStackAt(1); 5784 HValue* key = environment()->ExpressionStackAt(1);
5857 HValue* object = environment()->ExpressionStackAt(2); 5785 HValue* object = environment()->ExpressionStackAt(2);
5858 bool has_side_effects = false; 5786 bool has_side_effects = false;
5859 HandleKeyedElementAccess(object, key, value, expr, 5787 HandleKeyedElementAccess(object, key, value, expr,
5860 STORE, &has_side_effects); 5788 true, // is_store
5789 &has_side_effects);
5861 Drop(3); 5790 Drop(3);
5862 Push(value); 5791 Push(value);
5863 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); 5792 Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
5864 return ast_context()->ReturnValue(Pop()); 5793 return ast_context()->ReturnValue(Pop());
5865 } 5794 }
5866 5795
5867 // Named store. 5796 // Named store.
5868 HValue* value = Pop(); 5797 HValue* value = Pop();
5869 HValue* object = Pop(); 5798 HValue* object = Pop();
5870 5799
(...skipping 29 matching lines...) Expand all
5900 5829
5901 5830
5902 // Because not every expression has a position and there is not common 5831 // Because not every expression has a position and there is not common
5903 // superclass of Assignment and CountOperation, we cannot just pass the 5832 // superclass of Assignment and CountOperation, we cannot just pass the
5904 // owning expression instead of position and ast_id separately. 5833 // owning expression instead of position and ast_id separately.
5905 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( 5834 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
5906 Variable* var, 5835 Variable* var,
5907 HValue* value, 5836 HValue* value,
5908 BailoutId ast_id) { 5837 BailoutId ast_id) {
5909 LookupResult lookup(isolate()); 5838 LookupResult lookup(isolate());
5910 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, STORE); 5839 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
5911 if (type == kUseCell) { 5840 if (type == kUseCell) {
5912 Handle<GlobalObject> global(current_info()->global_object()); 5841 Handle<GlobalObject> global(current_info()->global_object());
5913 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 5842 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
5914 if (cell->type()->IsConstant()) { 5843 if (cell->type()->IsConstant()) {
5915 IfBuilder builder(this); 5844 IfBuilder builder(this);
5916 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); 5845 HValue* constant = Add<HConstant>(cell->type()->AsConstant());
5917 if (cell->type()->AsConstant()->IsNumber()) { 5846 if (cell->type()->AsConstant()->IsNumber()) {
5918 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); 5847 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ);
5919 } else { 5848 } else {
5920 builder.If<HCompareObjectEqAndBranch>(value, constant); 5849 builder.If<HCompareObjectEqAndBranch>(value, constant);
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
6184 ASSERT(!HasStackOverflow()); 6113 ASSERT(!HasStackOverflow());
6185 ASSERT(current_block() != NULL); 6114 ASSERT(current_block() != NULL);
6186 ASSERT(current_block()->HasPredecessor()); 6115 ASSERT(current_block()->HasPredecessor());
6187 // We don't optimize functions with invalid left-hand sides in 6116 // We don't optimize functions with invalid left-hand sides in
6188 // assignments, count operations, or for-in. Consequently throw can 6117 // assignments, count operations, or for-in. Consequently throw can
6189 // currently only occur in an effect context. 6118 // currently only occur in an effect context.
6190 ASSERT(ast_context()->IsEffect()); 6119 ASSERT(ast_context()->IsEffect());
6191 CHECK_ALIVE(VisitForValue(expr->exception())); 6120 CHECK_ALIVE(VisitForValue(expr->exception()));
6192 6121
6193 HValue* value = environment()->Pop(); 6122 HValue* value = environment()->Pop();
6194 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); 6123 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
6195 Add<HPushArgument>(value); 6124 Add<HPushArgument>(value);
6196 Add<HCallRuntime>(isolate()->factory()->empty_string(), 6125 Add<HCallRuntime>(isolate()->factory()->empty_string(),
6197 Runtime::FunctionForId(Runtime::kThrow), 1); 6126 Runtime::FunctionForId(Runtime::kThrow), 1);
6198 Add<HSimulate>(expr->id()); 6127 Add<HSimulate>(expr->id());
6199 6128
6200 // If the throw definitely exits the function, we can finish with a dummy 6129 // If the throw definitely exits the function, we can finish with a dummy
6201 // control flow at this point. This is not the case if the throw is inside 6130 // control flow at this point. This is not the case if the throw is inside
6202 // an inlined function which may be replaced. 6131 // an inlined function which may be replaced.
6203 if (call_context() == NULL) { 6132 if (call_context() == NULL) {
6204 FinishExitCurrentBlock(New<HAbnormalExit>()); 6133 FinishExitCurrentBlock(New<HAbnormalExit>());
6205 } 6134 }
6206 } 6135 }
6207 6136
6208 6137
6138 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
6139 HObjectAccess access) {
6140 if (FLAG_track_double_fields && access.representation().IsDouble()) {
6141 // load the heap number
6142 HLoadNamedField* heap_number = Add<HLoadNamedField>(
6143 object, static_cast<HValue*>(NULL),
6144 access.WithRepresentation(Representation::Tagged()));
6145 heap_number->set_type(HType::HeapNumber());
6146 // load the double value from it
6147 return New<HLoadNamedField>(
6148 heap_number, static_cast<HValue*>(NULL),
6149 HObjectAccess::ForHeapNumberValue());
6150 }
6151 return New<HLoadNamedField>(object, static_cast<HValue*>(NULL), access);
6152 }
6153
6154
6155 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object,
6156 HObjectAccess access) {
6157 return AddInstruction(BuildLoadNamedField(object, access));
6158 }
6159
6160
6209 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) { 6161 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
6210 if (string->IsConstant()) { 6162 if (string->IsConstant()) {
6211 HConstant* c_string = HConstant::cast(string); 6163 HConstant* c_string = HConstant::cast(string);
6212 if (c_string->HasStringValue()) { 6164 if (c_string->HasStringValue()) {
6213 return Add<HConstant>(c_string->StringValue()->map()->instance_type()); 6165 return Add<HConstant>(c_string->StringValue()->map()->instance_type());
6214 } 6166 }
6215 } 6167 }
6216 return Add<HLoadNamedField>( 6168 return AddLoadNamedField(
6217 Add<HLoadNamedField>(string, static_cast<HValue*>(NULL), 6169 AddLoadNamedField(string, HObjectAccess::ForMap()),
6218 HObjectAccess::ForMap()), 6170 HObjectAccess::ForMapInstanceType());
6219 static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
6220 } 6171 }
6221 6172
6222 6173
6223 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) { 6174 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
6224 if (string->IsConstant()) { 6175 if (string->IsConstant()) {
6225 HConstant* c_string = HConstant::cast(string); 6176 HConstant* c_string = HConstant::cast(string);
6226 if (c_string->HasStringValue()) { 6177 if (c_string->HasStringValue()) {
6227 return Add<HConstant>(c_string->StringValue()->length()); 6178 return Add<HConstant>(c_string->StringValue()->length());
6228 } 6179 }
6229 } 6180 }
6230 return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL), 6181 return AddLoadNamedField(string, HObjectAccess::ForStringLength());
6231 HObjectAccess::ForStringLength());
6232 } 6182 }
6233 6183
6234 6184
6235 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( 6185 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
6236 PropertyAccessType access_type,
6237 HValue* object, 6186 HValue* object,
6238 Handle<String> name, 6187 Handle<String> name,
6239 HValue* value,
6240 bool is_uninitialized) { 6188 bool is_uninitialized) {
6241 if (is_uninitialized) { 6189 if (is_uninitialized) {
6242 Add<HDeoptimize>("Insufficient type feedback for generic named access", 6190 Add<HDeoptimize>("Insufficient type feedback for generic named load",
6243 Deoptimizer::SOFT); 6191 Deoptimizer::SOFT);
6244 } 6192 }
6245 if (access_type == LOAD) { 6193 return New<HLoadNamedGeneric>(object, name);
6246 return New<HLoadNamedGeneric>(object, name);
6247 } else {
6248 return New<HStoreNamedGeneric>(
6249 object, name, value, function_strict_mode_flag());
6250 }
6251 } 6194 }
6252 6195
6253 6196
6254 6197
6255 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( 6198 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
6256 PropertyAccessType access_type, 6199 HValue* key) {
6257 HValue* object, 6200 return New<HLoadKeyedGeneric>(object, key);
6258 HValue* key,
6259 HValue* value) {
6260 if (access_type == LOAD) {
6261 return New<HLoadKeyedGeneric>(object, key);
6262 } else {
6263 return New<HStoreKeyedGeneric>(
6264 object, key, value, function_strict_mode_flag());
6265 }
6266 } 6201 }
6267 6202
6268 6203
6269 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { 6204 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
6270 // Loads from a "stock" fast holey double arrays can elide the hole check. 6205 // Loads from a "stock" fast holey double arrays can elide the hole check.
6271 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 6206 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
6272 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 6207 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
6273 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 6208 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
6274 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 6209 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
6275 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 6210 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
6276 BuildCheckPrototypeMaps(prototype, object_prototype); 6211 BuildCheckPrototypeMaps(prototype, object_prototype);
6277 load_mode = ALLOW_RETURN_HOLE; 6212 load_mode = ALLOW_RETURN_HOLE;
6278 graph()->MarkDependsOnEmptyArrayProtoElements(); 6213 graph()->MarkDependsOnEmptyArrayProtoElements();
6279 } 6214 }
6280 6215
6281 return load_mode; 6216 return load_mode;
6282 } 6217 }
6283 6218
6284 6219
6285 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( 6220 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
6286 HValue* object, 6221 HValue* object,
6287 HValue* key, 6222 HValue* key,
6288 HValue* val, 6223 HValue* val,
6289 HValue* dependency, 6224 HValue* dependency,
6290 Handle<Map> map, 6225 Handle<Map> map,
6291 PropertyAccessType access_type, 6226 bool is_store,
6292 KeyedAccessStoreMode store_mode) { 6227 KeyedAccessStoreMode store_mode) {
6293 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), 6228 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
6294 dependency); 6229 dependency);
6295 if (dependency) { 6230 if (dependency) {
6296 checked_object->ClearDependsOnFlag(kElementsKind); 6231 checked_object->ClearGVNFlag(kDependsOnElementsKind);
6297 } 6232 }
6298 6233
6299 if (access_type == STORE && map->prototype()->IsJSObject()) { 6234 if (is_store && map->prototype()->IsJSObject()) {
6300 // monomorphic stores need a prototype chain check because shape 6235 // monomorphic stores need a prototype chain check because shape
6301 // changes could allow callbacks on elements in the chain that 6236 // changes could allow callbacks on elements in the chain that
6302 // aren't compatible with monomorphic keyed stores. 6237 // aren't compatible with monomorphic keyed stores.
6303 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 6238 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
6304 Object* holder = map->prototype(); 6239 Object* holder = map->prototype();
6305 while (holder->GetPrototype(isolate())->IsJSObject()) { 6240 while (holder->GetPrototype(isolate())->IsJSObject()) {
6306 holder = holder->GetPrototype(isolate()); 6241 holder = holder->GetPrototype(isolate());
6307 } 6242 }
6308 ASSERT(holder->GetPrototype(isolate())->IsNull()); 6243 ASSERT(holder->GetPrototype(isolate())->IsNull());
6309 6244
6310 BuildCheckPrototypeMaps(prototype, 6245 BuildCheckPrototypeMaps(prototype,
6311 Handle<JSObject>(JSObject::cast(holder))); 6246 Handle<JSObject>(JSObject::cast(holder)));
6312 } 6247 }
6313 6248
6314 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); 6249 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
6315 return BuildUncheckedMonomorphicElementAccess( 6250 return BuildUncheckedMonomorphicElementAccess(
6316 checked_object, key, val, 6251 checked_object, key, val,
6317 map->instance_type() == JS_ARRAY_TYPE, 6252 map->instance_type() == JS_ARRAY_TYPE,
6318 map->elements_kind(), access_type, 6253 map->elements_kind(), is_store,
6319 load_mode, store_mode); 6254 load_mode, store_mode);
6320 } 6255 }
6321 6256
6322 6257
6323 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( 6258 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
6324 HValue* object, 6259 HValue* object,
6325 HValue* key, 6260 HValue* key,
6326 HValue* val, 6261 HValue* val,
6327 SmallMapList* maps) { 6262 SmallMapList* maps) {
6328 // For polymorphic loads of similar elements kinds (i.e. all tagged or all 6263 // For polymorphic loads of similar elements kinds (i.e. all tagged or all
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
6364 // Remember the most general elements kind, the code for its load will 6299 // Remember the most general elements kind, the code for its load will
6365 // properly handle all of the more specific cases. 6300 // properly handle all of the more specific cases.
6366 if ((i == 0) || IsMoreGeneralElementsKindTransition( 6301 if ((i == 0) || IsMoreGeneralElementsKindTransition(
6367 most_general_consolidated_map->elements_kind(), 6302 most_general_consolidated_map->elements_kind(),
6368 map->elements_kind())) { 6303 map->elements_kind())) {
6369 most_general_consolidated_map = map; 6304 most_general_consolidated_map = map;
6370 } 6305 }
6371 } 6306 }
6372 if (!has_double_maps && !has_smi_or_object_maps) return NULL; 6307 if (!has_double_maps && !has_smi_or_object_maps) return NULL;
6373 6308
6374 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps, top_info()); 6309 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
6375 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS. 6310 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
6376 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS. 6311 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
6377 ElementsKind consolidated_elements_kind = has_seen_holey_elements 6312 ElementsKind consolidated_elements_kind = has_seen_holey_elements
6378 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind()) 6313 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
6379 : most_general_consolidated_map->elements_kind(); 6314 : most_general_consolidated_map->elements_kind();
6380 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 6315 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6381 checked_object, key, val, 6316 checked_object, key, val,
6382 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 6317 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
6383 consolidated_elements_kind, 6318 consolidated_elements_kind,
6384 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); 6319 false, NEVER_RETURN_HOLE, STANDARD_STORE);
6385 return instr; 6320 return instr;
6386 } 6321 }
6387 6322
6388 6323
6389 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 6324 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
6390 HValue* object, 6325 HValue* object,
6391 HValue* key, 6326 HValue* key,
6392 HValue* val, 6327 HValue* val,
6393 SmallMapList* maps, 6328 SmallMapList* maps,
6394 PropertyAccessType access_type, 6329 bool is_store,
6395 KeyedAccessStoreMode store_mode, 6330 KeyedAccessStoreMode store_mode,
6396 bool* has_side_effects) { 6331 bool* has_side_effects) {
6397 *has_side_effects = false; 6332 *has_side_effects = false;
6398 BuildCheckHeapObject(object); 6333 BuildCheckHeapObject(object);
6399 6334
6400 if (access_type == LOAD) { 6335 if (!is_store) {
6401 HInstruction* consolidated_load = 6336 HInstruction* consolidated_load =
6402 TryBuildConsolidatedElementLoad(object, key, val, maps); 6337 TryBuildConsolidatedElementLoad(object, key, val, maps);
6403 if (consolidated_load != NULL) { 6338 if (consolidated_load != NULL) {
6404 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 6339 *has_side_effects |= consolidated_load->HasObservableSideEffects();
6405 return consolidated_load; 6340 return consolidated_load;
6406 } 6341 }
6407 } 6342 }
6408 6343
6409 // Elements_kind transition support. 6344 // Elements_kind transition support.
6410 MapHandleList transition_target(maps->length()); 6345 MapHandleList transition_target(maps->length());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
6443 } 6378 }
6444 6379
6445 // If only one map is left after transitioning, handle this case 6380 // If only one map is left after transitioning, handle this case
6446 // monomorphically. 6381 // monomorphically.
6447 ASSERT(untransitionable_maps.length() >= 1); 6382 ASSERT(untransitionable_maps.length() >= 1);
6448 if (untransitionable_maps.length() == 1) { 6383 if (untransitionable_maps.length() == 1) {
6449 Handle<Map> untransitionable_map = untransitionable_maps[0]; 6384 Handle<Map> untransitionable_map = untransitionable_maps[0];
6450 HInstruction* instr = NULL; 6385 HInstruction* instr = NULL;
6451 if (untransitionable_map->has_slow_elements_kind() || 6386 if (untransitionable_map->has_slow_elements_kind() ||
6452 !untransitionable_map->IsJSObjectMap()) { 6387 !untransitionable_map->IsJSObjectMap()) {
6453 instr = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); 6388 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
6389 : BuildLoadKeyedGeneric(object, key));
6454 } else { 6390 } else {
6455 instr = BuildMonomorphicElementAccess( 6391 instr = BuildMonomorphicElementAccess(
6456 object, key, val, transition, untransitionable_map, access_type, 6392 object, key, val, transition, untransitionable_map, is_store,
6457 store_mode); 6393 store_mode);
6458 } 6394 }
6459 *has_side_effects |= instr->HasObservableSideEffects(); 6395 *has_side_effects |= instr->HasObservableSideEffects();
6460 return access_type == STORE ? NULL : instr; 6396 return is_store ? NULL : instr;
6461 } 6397 }
6462 6398
6463 HBasicBlock* join = graph()->CreateBasicBlock(); 6399 HBasicBlock* join = graph()->CreateBasicBlock();
6464 6400
6465 for (int i = 0; i < untransitionable_maps.length(); ++i) { 6401 for (int i = 0; i < untransitionable_maps.length(); ++i) {
6466 Handle<Map> map = untransitionable_maps[i]; 6402 Handle<Map> map = untransitionable_maps[i];
6467 if (!map->IsJSObjectMap()) continue; 6403 if (!map->IsJSObjectMap()) continue;
6468 ElementsKind elements_kind = map->elements_kind(); 6404 ElementsKind elements_kind = map->elements_kind();
6469 HBasicBlock* this_map = graph()->CreateBasicBlock(); 6405 HBasicBlock* this_map = graph()->CreateBasicBlock();
6470 HBasicBlock* other_map = graph()->CreateBasicBlock(); 6406 HBasicBlock* other_map = graph()->CreateBasicBlock();
6471 HCompareMap* mapcompare = 6407 HCompareMap* mapcompare =
6472 New<HCompareMap>(object, map, top_info(), this_map, other_map); 6408 New<HCompareMap>(object, map, this_map, other_map);
6473 FinishCurrentBlock(mapcompare); 6409 FinishCurrentBlock(mapcompare);
6474 6410
6475 set_current_block(this_map); 6411 set_current_block(this_map);
6476 HInstruction* access = NULL; 6412 HInstruction* access = NULL;
6477 if (IsDictionaryElementsKind(elements_kind)) { 6413 if (IsDictionaryElementsKind(elements_kind)) {
6478 access = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); 6414 access = is_store
6415 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
6416 : AddInstruction(BuildLoadKeyedGeneric(object, key));
6479 } else { 6417 } else {
6480 ASSERT(IsFastElementsKind(elements_kind) || 6418 ASSERT(IsFastElementsKind(elements_kind) ||
6481 IsExternalArrayElementsKind(elements_kind)); 6419 IsExternalArrayElementsKind(elements_kind));
6482 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); 6420 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
6483 // Happily, mapcompare is a checked object. 6421 // Happily, mapcompare is a checked object.
6484 access = BuildUncheckedMonomorphicElementAccess( 6422 access = BuildUncheckedMonomorphicElementAccess(
6485 mapcompare, key, val, 6423 mapcompare, key, val,
6486 map->instance_type() == JS_ARRAY_TYPE, 6424 map->instance_type() == JS_ARRAY_TYPE,
6487 elements_kind, access_type, 6425 elements_kind, is_store,
6488 load_mode, 6426 load_mode,
6489 store_mode); 6427 store_mode);
6490 } 6428 }
6491 *has_side_effects |= access->HasObservableSideEffects(); 6429 *has_side_effects |= access->HasObservableSideEffects();
6492 // The caller will use has_side_effects and add a correct Simulate. 6430 // The caller will use has_side_effects and add a correct Simulate.
6493 access->SetFlag(HValue::kHasNoObservableSideEffects); 6431 access->SetFlag(HValue::kHasNoObservableSideEffects);
6494 if (access_type == LOAD) { 6432 if (!is_store) {
6495 Push(access); 6433 Push(access);
6496 } 6434 }
6497 NoObservableSideEffectsScope scope(this); 6435 NoObservableSideEffectsScope scope(this);
6498 GotoNoSimulate(join); 6436 GotoNoSimulate(join);
6499 set_current_block(other_map); 6437 set_current_block(other_map);
6500 } 6438 }
6501 6439
6502 // Ensure that we visited at least one map above that goes to join. This is
6503 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
6504 // rather than joining the join block. If this becomes an issue, insert a
6505 // generic access in the case length() == 0.
6506 ASSERT(join->predecessors()->length() > 0);
6507 // Deopt if none of the cases matched. 6440 // Deopt if none of the cases matched.
6508 NoObservableSideEffectsScope scope(this); 6441 NoObservableSideEffectsScope scope(this);
6509 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access"); 6442 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access",
6443 join);
6510 set_current_block(join); 6444 set_current_block(join);
6511 return access_type == STORE ? NULL : Pop(); 6445 return is_store ? NULL : Pop();
6512 } 6446 }
6513 6447
6514 6448
6515 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( 6449 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
6516 HValue* obj, 6450 HValue* obj,
6517 HValue* key, 6451 HValue* key,
6518 HValue* val, 6452 HValue* val,
6519 Expression* expr, 6453 Expression* expr,
6520 PropertyAccessType access_type, 6454 bool is_store,
6521 bool* has_side_effects) { 6455 bool* has_side_effects) {
6522 ASSERT(!expr->IsPropertyName()); 6456 ASSERT(!expr->IsPropertyName());
6523 HInstruction* instr = NULL; 6457 HInstruction* instr = NULL;
6524 6458
6525 SmallMapList* types; 6459 SmallMapList* types;
6526 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); 6460 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
6527 6461
6528 bool force_generic = false; 6462 bool force_generic = false;
6529 if (access_type == STORE && 6463 if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) {
6530 (monomorphic || (types != NULL && !types->is_empty()))) {
6531 // Stores can't be mono/polymorphic if their prototype chain has dictionary 6464 // Stores can't be mono/polymorphic if their prototype chain has dictionary
6532 // elements. However a receiver map that has dictionary elements itself 6465 // elements. However a receiver map that has dictionary elements itself
6533 // should be left to normal mono/poly behavior (the other maps may benefit 6466 // should be left to normal mono/poly behavior (the other maps may benefit
6534 // from highly optimized stores). 6467 // from highly optimized stores).
6535 for (int i = 0; i < types->length(); i++) { 6468 for (int i = 0; i < types->length(); i++) {
6536 Handle<Map> current_map = types->at(i); 6469 Handle<Map> current_map = types->at(i);
6537 if (current_map->DictionaryElementsInPrototypeChainOnly()) { 6470 if (current_map->DictionaryElementsInPrototypeChainOnly()) {
6538 force_generic = true; 6471 force_generic = true;
6539 monomorphic = false; 6472 monomorphic = false;
6540 break; 6473 break;
6541 } 6474 }
6542 } 6475 }
6543 } 6476 }
6544 6477
6545 if (monomorphic) { 6478 if (monomorphic) {
6546 Handle<Map> map = types->first(); 6479 Handle<Map> map = types->first();
6547 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { 6480 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
6548 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); 6481 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
6482 : BuildLoadKeyedGeneric(obj, key);
6483 AddInstruction(instr);
6549 } else { 6484 } else {
6550 BuildCheckHeapObject(obj); 6485 BuildCheckHeapObject(obj);
6551 instr = BuildMonomorphicElementAccess( 6486 instr = BuildMonomorphicElementAccess(
6552 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); 6487 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
6553 } 6488 }
6554 } else if (!force_generic && (types != NULL && !types->is_empty())) { 6489 } else if (!force_generic && (types != NULL && !types->is_empty())) {
6555 return HandlePolymorphicElementAccess( 6490 return HandlePolymorphicElementAccess(
6556 obj, key, val, types, access_type, 6491 obj, key, val, types, is_store,
6557 expr->GetStoreMode(), has_side_effects); 6492 expr->GetStoreMode(), has_side_effects);
6558 } else { 6493 } else {
6559 if (access_type == STORE) { 6494 if (is_store) {
6560 if (expr->IsAssignment() && 6495 if (expr->IsAssignment() &&
6561 expr->AsAssignment()->HasNoTypeInformation()) { 6496 expr->AsAssignment()->HasNoTypeInformation()) {
6562 Add<HDeoptimize>("Insufficient type feedback for keyed store", 6497 Add<HDeoptimize>("Insufficient type feedback for keyed store",
6563 Deoptimizer::SOFT); 6498 Deoptimizer::SOFT);
6564 } 6499 }
6500 instr = BuildStoreKeyedGeneric(obj, key, val);
6565 } else { 6501 } else {
6566 if (expr->AsProperty()->HasNoTypeInformation()) { 6502 if (expr->AsProperty()->HasNoTypeInformation()) {
6567 Add<HDeoptimize>("Insufficient type feedback for keyed load", 6503 Add<HDeoptimize>("Insufficient type feedback for keyed load",
6568 Deoptimizer::SOFT); 6504 Deoptimizer::SOFT);
6569 } 6505 }
6506 instr = BuildLoadKeyedGeneric(obj, key);
6570 } 6507 }
6571 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); 6508 AddInstruction(instr);
6572 } 6509 }
6573 *has_side_effects = instr->HasObservableSideEffects(); 6510 *has_side_effects = instr->HasObservableSideEffects();
6574 return instr; 6511 return instr;
6575 } 6512 }
6576 6513
6577 6514
6515 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
6516 HValue* object,
6517 HValue* key,
6518 HValue* value) {
6519 return New<HStoreKeyedGeneric>(
6520 object,
6521 key,
6522 value,
6523 function_strict_mode_flag());
6524 }
6525
6526
6578 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { 6527 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
6579 // Outermost function already has arguments on the stack. 6528 // Outermost function already has arguments on the stack.
6580 if (function_state()->outer() == NULL) return; 6529 if (function_state()->outer() == NULL) return;
6581 6530
6582 if (function_state()->arguments_pushed()) return; 6531 if (function_state()->arguments_pushed()) return;
6583 6532
6584 // Push arguments when entering inlined function. 6533 // Push arguments when entering inlined function.
6585 HEnterInlined* entry = function_state()->entry(); 6534 HEnterInlined* entry = function_state()->entry();
6586 entry->set_arguments_pushed(); 6535 entry->set_arguments_pushed();
6587 6536
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
6674 } 6623 }
6675 6624
6676 HValue* checked_object; 6625 HValue* checked_object;
6677 // Type::Number() is only supported by polymorphic load/call handling. 6626 // Type::Number() is only supported by polymorphic load/call handling.
6678 ASSERT(!info.type()->Is(Type::Number())); 6627 ASSERT(!info.type()->Is(Type::Number()));
6679 BuildCheckHeapObject(object); 6628 BuildCheckHeapObject(object);
6680 if (AreStringTypes(types)) { 6629 if (AreStringTypes(types)) {
6681 checked_object = 6630 checked_object =
6682 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); 6631 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
6683 } else { 6632 } else {
6684 checked_object = Add<HCheckMaps>(object, types, top_info()); 6633 checked_object = Add<HCheckMaps>(object, types);
6685 } 6634 }
6686 return BuildMonomorphicAccess( 6635 return BuildMonomorphicAccess(
6687 &info, object, checked_object, value, ast_id, return_id); 6636 &info, object, checked_object, value, ast_id, return_id);
6688 } 6637 }
6689 6638
6690 return BuildNamedGeneric(access, object, name, value, is_uninitialized); 6639 if (access == LOAD) {
6640 return BuildLoadNamedGeneric(object, name, is_uninitialized);
6641 } else {
6642 return BuildStoreNamedGeneric(object, name, value, is_uninitialized);
6643 }
6691 } 6644 }
6692 6645
6693 6646
6694 void HOptimizedGraphBuilder::PushLoad(Property* expr, 6647 void HOptimizedGraphBuilder::PushLoad(Property* expr,
6695 HValue* object, 6648 HValue* object,
6696 HValue* key) { 6649 HValue* key) {
6697 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 6650 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
6698 Push(object); 6651 Push(object);
6699 if (key != NULL) Push(key); 6652 if (key != NULL) Push(key);
6700 BuildLoad(expr, expr->LoadId()); 6653 BuildLoad(expr, expr->LoadId());
(...skipping 23 matching lines...) Expand all
6724 object, name, NULL, expr->IsUninitialized()); 6677 object, name, NULL, expr->IsUninitialized());
6725 if (instr == NULL) return; 6678 if (instr == NULL) return;
6726 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); 6679 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
6727 6680
6728 } else { 6681 } else {
6729 HValue* key = Pop(); 6682 HValue* key = Pop();
6730 HValue* obj = Pop(); 6683 HValue* obj = Pop();
6731 6684
6732 bool has_side_effects = false; 6685 bool has_side_effects = false;
6733 HValue* load = HandleKeyedElementAccess( 6686 HValue* load = HandleKeyedElementAccess(
6734 obj, key, NULL, expr, LOAD, &has_side_effects); 6687 obj, key, NULL, expr,
6688 false, // is_store
6689 &has_side_effects);
6735 if (has_side_effects) { 6690 if (has_side_effects) {
6736 if (ast_context()->IsEffect()) { 6691 if (ast_context()->IsEffect()) {
6737 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6692 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6738 } else { 6693 } else {
6739 Push(load); 6694 Push(load);
6740 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6695 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6741 Drop(1); 6696 Drop(1);
6742 } 6697 }
6743 } 6698 }
6744 return ast_context()->ReturnValue(load); 6699 return ast_context()->ReturnValue(load);
(...skipping 25 matching lines...) Expand all
6770 6725
6771 if (constant->map()->CanOmitMapChecks()) { 6726 if (constant->map()->CanOmitMapChecks()) {
6772 constant->map()->AddDependentCompilationInfo( 6727 constant->map()->AddDependentCompilationInfo(
6773 DependentCode::kPrototypeCheckGroup, info); 6728 DependentCode::kPrototypeCheckGroup, info);
6774 return constant_value; 6729 return constant_value;
6775 } 6730 }
6776 6731
6777 AddInstruction(constant_value); 6732 AddInstruction(constant_value);
6778 HCheckMaps* check = 6733 HCheckMaps* check =
6779 Add<HCheckMaps>(constant_value, handle(constant->map()), info); 6734 Add<HCheckMaps>(constant_value, handle(constant->map()), info);
6780 check->ClearDependsOnFlag(kElementsKind); 6735 check->ClearGVNFlag(kDependsOnElementsKind);
6781 return check; 6736 return check;
6782 } 6737 }
6783 6738
6784 6739
6785 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, 6740 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
6786 Handle<JSObject> holder) { 6741 Handle<JSObject> holder) {
6787 while (!prototype.is_identical_to(holder)) { 6742 while (!prototype.is_identical_to(holder)) {
6788 BuildConstantMapCheck(prototype, top_info()); 6743 BuildConstantMapCheck(prototype, top_info());
6789 prototype = handle(JSObject::cast(prototype->GetPrototype())); 6744 prototype = handle(JSObject::cast(prototype->GetPrototype()));
6790 } 6745 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
6854 target, static_cast<HValue*>(NULL), 6809 target, static_cast<HValue*>(NULL),
6855 HObjectAccess::ForFunctionContextPointer()); 6810 HObjectAccess::ForFunctionContextPointer());
6856 return NewArgumentAdaptorCall(target, context, 6811 return NewArgumentAdaptorCall(target, context,
6857 argument_count, param_count_value); 6812 argument_count, param_count_value);
6858 } 6813 }
6859 UNREACHABLE(); 6814 UNREACHABLE();
6860 return NULL; 6815 return NULL;
6861 } 6816 }
6862 6817
6863 6818
6819 class FunctionSorter {
6820 public:
6821 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { }
6822 FunctionSorter(int index, int ticks, int ast_length, int src_length)
6823 : index_(index),
6824 ticks_(ticks),
6825 ast_length_(ast_length),
6826 src_length_(src_length) { }
6827
6828 int index() const { return index_; }
6829 int ticks() const { return ticks_; }
6830 int ast_length() const { return ast_length_; }
6831 int src_length() const { return src_length_; }
6832
6833 private:
6834 int index_;
6835 int ticks_;
6836 int ast_length_;
6837 int src_length_;
6838 };
6839
6840
6841 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
6842 int diff = lhs.ticks() - rhs.ticks();
6843 if (diff != 0) return diff > 0;
6844 diff = lhs.ast_length() - rhs.ast_length();
6845 if (diff != 0) return diff < 0;
6846 return lhs.src_length() < rhs.src_length();
6847 }
6848
6849
6864 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( 6850 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
6865 Call* expr, 6851 Call* expr,
6866 HValue* receiver, 6852 HValue* receiver,
6867 SmallMapList* types, 6853 SmallMapList* types,
6868 Handle<String> name) { 6854 Handle<String> name) {
6869 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6855 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6870 int order[kMaxCallPolymorphism]; 6856 FunctionSorter order[kMaxCallPolymorphism];
6871 6857
6872 bool handle_smi = false; 6858 bool handle_smi = false;
6873 bool handled_string = false; 6859 bool handled_string = false;
6874 int ordered_functions = 0; 6860 int ordered_functions = 0;
6875 6861
6876 for (int i = 0; 6862 for (int i = 0;
6877 i < types->length() && ordered_functions < kMaxCallPolymorphism; 6863 i < types->length() && ordered_functions < kMaxCallPolymorphism;
6878 ++i) { 6864 ++i) {
6879 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); 6865 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
6880 if (info.CanAccessMonomorphic() && 6866 if (info.CanAccessMonomorphic() &&
6881 info.lookup()->IsConstant() && 6867 info.lookup()->IsConstant() &&
6882 info.constant()->IsJSFunction()) { 6868 info.constant()->IsJSFunction()) {
6883 if (info.type()->Is(Type::String())) { 6869 if (info.type()->Is(Type::String())) {
6884 if (handled_string) continue; 6870 if (handled_string) continue;
6885 handled_string = true; 6871 handled_string = true;
6886 } 6872 }
6887 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); 6873 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
6888 if (info.type()->Is(Type::Number())) { 6874 if (info.type()->Is(Type::Number())) {
6889 handle_smi = true; 6875 handle_smi = true;
6890 } 6876 }
6891 expr->set_target(target); 6877 expr->set_target(target);
6892 order[ordered_functions++] = i; 6878 order[ordered_functions++] =
6879 FunctionSorter(i,
6880 expr->target()->shared()->profiler_ticks(),
6881 InliningAstSize(expr->target()),
6882 expr->target()->shared()->SourceSize());
6893 } 6883 }
6894 } 6884 }
6895 6885
6886 std::sort(order, order + ordered_functions);
6887
6896 HBasicBlock* number_block = NULL; 6888 HBasicBlock* number_block = NULL;
6897 HBasicBlock* join = NULL; 6889 HBasicBlock* join = NULL;
6898 handled_string = false; 6890 handled_string = false;
6899 int count = 0; 6891 int count = 0;
6900 6892
6901 for (int fn = 0; fn < ordered_functions; ++fn) { 6893 for (int fn = 0; fn < ordered_functions; ++fn) {
6902 int i = order[fn]; 6894 int i = order[fn].index();
6903 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); 6895 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
6904 if (info.type()->Is(Type::String())) { 6896 if (info.type()->Is(Type::String())) {
6905 if (handled_string) continue; 6897 if (handled_string) continue;
6906 handled_string = true; 6898 handled_string = true;
6907 } 6899 }
6908 // Reloads the target. 6900 // Reloads the target.
6909 info.CanAccessMonomorphic(); 6901 info.CanAccessMonomorphic();
6910 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); 6902 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
6911 6903
6912 expr->set_target(target); 6904 expr->set_target(target);
6913 if (count == 0) { 6905 if (count == 0) {
6914 // Only needed once. 6906 // Only needed once.
6915 join = graph()->CreateBasicBlock(); 6907 join = graph()->CreateBasicBlock();
6916 if (handle_smi) { 6908 if (handle_smi) {
6917 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 6909 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6918 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 6910 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6919 number_block = graph()->CreateBasicBlock(); 6911 number_block = graph()->CreateBasicBlock();
6920 FinishCurrentBlock(New<HIsSmiAndBranch>( 6912 FinishCurrentBlock(New<HIsSmiAndBranch>(
6921 receiver, empty_smi_block, not_smi_block)); 6913 receiver, empty_smi_block, not_smi_block));
6922 GotoNoSimulate(empty_smi_block, number_block); 6914 Goto(empty_smi_block, number_block);
6923 set_current_block(not_smi_block); 6915 set_current_block(not_smi_block);
6924 } else { 6916 } else {
6925 BuildCheckHeapObject(receiver); 6917 BuildCheckHeapObject(receiver);
6926 } 6918 }
6927 } 6919 }
6928 ++count; 6920 ++count;
6929 HBasicBlock* if_true = graph()->CreateBasicBlock(); 6921 HBasicBlock* if_true = graph()->CreateBasicBlock();
6930 HBasicBlock* if_false = graph()->CreateBasicBlock(); 6922 HBasicBlock* if_false = graph()->CreateBasicBlock();
6931 HUnaryControlInstruction* compare; 6923 HUnaryControlInstruction* compare;
6932 6924
6933 Handle<Map> map = info.map(); 6925 Handle<Map> map = info.map();
6934 if (info.type()->Is(Type::Number())) { 6926 if (info.type()->Is(Type::Number())) {
6935 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); 6927 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6936 compare = New<HCompareMap>(receiver, heap_number_map, top_info(), 6928 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
6937 if_true, if_false);
6938 } else if (info.type()->Is(Type::String())) { 6929 } else if (info.type()->Is(Type::String())) {
6939 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); 6930 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
6940 } else { 6931 } else {
6941 compare = New<HCompareMap>(receiver, map, top_info(), 6932 compare = New<HCompareMap>(receiver, map, if_true, if_false);
6942 if_true, if_false);
6943 } 6933 }
6944 FinishCurrentBlock(compare); 6934 FinishCurrentBlock(compare);
6945 6935
6946 if (info.type()->Is(Type::Number())) { 6936 if (info.type()->Is(Type::Number())) {
6947 GotoNoSimulate(if_true, number_block); 6937 Goto(if_true, number_block);
6948 if_true = number_block; 6938 if_true = number_block;
6939 number_block->SetJoinId(expr->id());
6949 } 6940 }
6950 6941
6951 set_current_block(if_true); 6942 set_current_block(if_true);
6952 6943
6953 AddCheckPrototypeMaps(info.holder(), map); 6944 AddCheckPrototypeMaps(info.holder(), map);
6954 6945
6955 HValue* function = Add<HConstant>(expr->target()); 6946 HValue* function = Add<HConstant>(expr->target());
6956 environment()->SetExpressionStackAt(0, function); 6947 environment()->SetExpressionStackAt(0, function);
6957 Push(receiver); 6948 Push(receiver);
6958 CHECK_ALIVE(VisitExpressions(expr->arguments())); 6949 CHECK_ALIVE(VisitExpressions(expr->arguments()));
(...skipping 27 matching lines...) Expand all
6986 } 6977 }
6987 6978
6988 if (current_block() != NULL) Goto(join); 6979 if (current_block() != NULL) Goto(join);
6989 set_current_block(if_false); 6980 set_current_block(if_false);
6990 } 6981 }
6991 6982
6992 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6983 // Finish up. Unconditionally deoptimize if we've handled all the maps we
6993 // know about and do not want to handle ones we've never seen. Otherwise 6984 // know about and do not want to handle ones we've never seen. Otherwise
6994 // use a generic IC. 6985 // use a generic IC.
6995 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 6986 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
6996 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); 6987 // Because the deopt may be the only path in the polymorphic call, make sure
6988 // that the environment stack matches the depth on deopt that it otherwise
6989 // would have had after a successful call.
6990 Drop(1); // Drop receiver.
6991 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
6992 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
6997 } else { 6993 } else {
6998 Property* prop = expr->expression()->AsProperty(); 6994 Property* prop = expr->expression()->AsProperty();
6999 HInstruction* function = BuildNamedGeneric( 6995 HInstruction* function = BuildLoadNamedGeneric(
7000 LOAD, receiver, name, NULL, prop->IsUninitialized()); 6996 receiver, name, prop->IsUninitialized());
7001 AddInstruction(function); 6997 AddInstruction(function);
7002 Push(function); 6998 Push(function);
7003 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); 6999 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
7004 7000
7005 environment()->SetExpressionStackAt(1, function); 7001 environment()->SetExpressionStackAt(1, function);
7006 environment()->SetExpressionStackAt(0, receiver); 7002 environment()->SetExpressionStackAt(0, receiver);
7007 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7003 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7008 7004
7009 CallFunctionFlags flags = receiver->type().IsJSObject() 7005 CallFunctionFlags flags = receiver->type().IsJSObject()
7010 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; 7006 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
7094 int nodes_added = target_shared->ast_node_count(); 7090 int nodes_added = target_shared->ast_node_count();
7095 return nodes_added; 7091 return nodes_added;
7096 } 7092 }
7097 7093
7098 7094
7099 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, 7095 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
7100 int arguments_count, 7096 int arguments_count,
7101 HValue* implicit_return_value, 7097 HValue* implicit_return_value,
7102 BailoutId ast_id, 7098 BailoutId ast_id,
7103 BailoutId return_id, 7099 BailoutId return_id,
7104 InliningKind inlining_kind, 7100 InliningKind inlining_kind) {
7105 HSourcePosition position) {
7106 int nodes_added = InliningAstSize(target); 7101 int nodes_added = InliningAstSize(target);
7107 if (nodes_added == kNotInlinable) return false; 7102 if (nodes_added == kNotInlinable) return false;
7108 7103
7109 Handle<JSFunction> caller = current_info()->closure(); 7104 Handle<JSFunction> caller = current_info()->closure();
7110 7105
7111 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 7106 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7112 TraceInline(target, caller, "target AST is too large [early]"); 7107 TraceInline(target, caller, "target AST is too large [early]");
7113 return false; 7108 return false;
7114 } 7109 }
7115 7110
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
7227 } 7222 }
7228 7223
7229 // ---------------------------------------------------------------- 7224 // ----------------------------------------------------------------
7230 // After this point, we've made a decision to inline this function (so 7225 // After this point, we've made a decision to inline this function (so
7231 // TryInline should always return true). 7226 // TryInline should always return true).
7232 7227
7233 // Type-check the inlined function. 7228 // Type-check the inlined function.
7234 ASSERT(target_shared->has_deoptimization_support()); 7229 ASSERT(target_shared->has_deoptimization_support());
7235 AstTyper::Run(&target_info); 7230 AstTyper::Run(&target_info);
7236 7231
7237 int function_id = graph()->TraceInlinedFunction(target_shared, position);
7238
7239 // Save the pending call context. Set up new one for the inlined function. 7232 // Save the pending call context. Set up new one for the inlined function.
7240 // The function state is new-allocated because we need to delete it 7233 // The function state is new-allocated because we need to delete it
7241 // in two different places. 7234 // in two different places.
7242 FunctionState* target_state = new FunctionState( 7235 FunctionState* target_state = new FunctionState(
7243 this, &target_info, inlining_kind, function_id); 7236 this, &target_info, inlining_kind);
7244 7237
7245 HConstant* undefined = graph()->GetConstantUndefined(); 7238 HConstant* undefined = graph()->GetConstantUndefined();
7246 7239
7247 HEnvironment* inner_env = 7240 HEnvironment* inner_env =
7248 environment()->CopyForInlining(target, 7241 environment()->CopyForInlining(target,
7249 arguments_count, 7242 arguments_count,
7250 function, 7243 function,
7251 undefined, 7244 undefined,
7252 function_state()->inlining_kind()); 7245 function_state()->inlining_kind());
7253 7246
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
7380 return true; 7373 return true;
7381 } 7374 }
7382 7375
7383 7376
7384 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) { 7377 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
7385 return TryInline(expr->target(), 7378 return TryInline(expr->target(),
7386 expr->arguments()->length(), 7379 expr->arguments()->length(),
7387 NULL, 7380 NULL,
7388 expr->id(), 7381 expr->id(),
7389 expr->ReturnId(), 7382 expr->ReturnId(),
7390 NORMAL_RETURN, 7383 NORMAL_RETURN);
7391 ScriptPositionToSourcePosition(expr->position()));
7392 } 7384 }
7393 7385
7394 7386
7395 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, 7387 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
7396 HValue* implicit_return_value) { 7388 HValue* implicit_return_value) {
7397 return TryInline(expr->target(), 7389 return TryInline(expr->target(),
7398 expr->arguments()->length(), 7390 expr->arguments()->length(),
7399 implicit_return_value, 7391 implicit_return_value,
7400 expr->id(), 7392 expr->id(),
7401 expr->ReturnId(), 7393 expr->ReturnId(),
7402 CONSTRUCT_CALL_RETURN, 7394 CONSTRUCT_CALL_RETURN);
7403 ScriptPositionToSourcePosition(expr->position()));
7404 } 7395 }
7405 7396
7406 7397
7407 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, 7398 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
7408 Handle<Map> receiver_map, 7399 Handle<Map> receiver_map,
7409 BailoutId ast_id, 7400 BailoutId ast_id,
7410 BailoutId return_id) { 7401 BailoutId return_id) {
7411 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; 7402 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
7412 return TryInline(getter, 7403 return TryInline(getter,
7413 0, 7404 0,
7414 NULL, 7405 NULL,
7415 ast_id, 7406 ast_id,
7416 return_id, 7407 return_id,
7417 GETTER_CALL_RETURN, 7408 GETTER_CALL_RETURN);
7418 source_position());
7419 } 7409 }
7420 7410
7421 7411
7422 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, 7412 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
7423 Handle<Map> receiver_map, 7413 Handle<Map> receiver_map,
7424 BailoutId id, 7414 BailoutId id,
7425 BailoutId assignment_id, 7415 BailoutId assignment_id,
7426 HValue* implicit_return_value) { 7416 HValue* implicit_return_value) {
7427 if (TryInlineApiSetter(setter, receiver_map, id)) return true; 7417 if (TryInlineApiSetter(setter, receiver_map, id)) return true;
7428 return TryInline(setter, 7418 return TryInline(setter,
7429 1, 7419 1,
7430 implicit_return_value, 7420 implicit_return_value,
7431 id, assignment_id, 7421 id, assignment_id,
7432 SETTER_CALL_RETURN, 7422 SETTER_CALL_RETURN);
7433 source_position());
7434 } 7423 }
7435 7424
7436 7425
7437 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, 7426 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
7438 Call* expr, 7427 Call* expr,
7439 int arguments_count) { 7428 int arguments_count) {
7440 return TryInline(function, 7429 return TryInline(function,
7441 arguments_count, 7430 arguments_count,
7442 NULL, 7431 NULL,
7443 expr->id(), 7432 expr->id(),
7444 expr->ReturnId(), 7433 expr->ReturnId(),
7445 NORMAL_RETURN, 7434 NORMAL_RETURN);
7446 ScriptPositionToSourcePosition(expr->position()));
7447 } 7435 }
7448 7436
7449 7437
7450 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) { 7438 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
7451 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 7439 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
7452 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7440 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7453 switch (id) { 7441 switch (id) {
7454 case kMathExp: 7442 case kMathExp:
7455 if (!FLAG_fast_math) break; 7443 if (!FLAG_fast_math) break;
7456 // Fall through if FLAG_fast_math. 7444 // Fall through if FLAG_fast_math.
7457 case kMathRound: 7445 case kMathRound:
7458 case kMathFloor: 7446 case kMathFloor:
7459 case kMathAbs: 7447 case kMathAbs:
7460 case kMathSqrt: 7448 case kMathSqrt:
7461 case kMathLog: 7449 case kMathLog:
7462 case kMathClz32:
7463 if (expr->arguments()->length() == 1) { 7450 if (expr->arguments()->length() == 1) {
7464 HValue* argument = Pop(); 7451 HValue* argument = Pop();
7465 Drop(2); // Receiver and function. 7452 Drop(2); // Receiver and function.
7466 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7453 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7467 ast_context()->ReturnInstruction(op, expr->id()); 7454 ast_context()->ReturnInstruction(op, expr->id());
7468 return true; 7455 return true;
7469 } 7456 }
7470 break; 7457 break;
7471 case kMathImul: 7458 case kMathImul:
7472 if (expr->arguments()->length() == 2) { 7459 if (expr->arguments()->length() == 2) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
7523 } 7510 }
7524 break; 7511 break;
7525 case kMathExp: 7512 case kMathExp:
7526 if (!FLAG_fast_math) break; 7513 if (!FLAG_fast_math) break;
7527 // Fall through if FLAG_fast_math. 7514 // Fall through if FLAG_fast_math.
7528 case kMathRound: 7515 case kMathRound:
7529 case kMathFloor: 7516 case kMathFloor:
7530 case kMathAbs: 7517 case kMathAbs:
7531 case kMathSqrt: 7518 case kMathSqrt:
7532 case kMathLog: 7519 case kMathLog:
7533 case kMathClz32:
7534 if (argument_count == 2) { 7520 if (argument_count == 2) {
7535 HValue* argument = Pop(); 7521 HValue* argument = Pop();
7536 Drop(2); // Receiver and function. 7522 Drop(2); // Receiver and function.
7537 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7523 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7538 ast_context()->ReturnInstruction(op, expr->id()); 7524 ast_context()->ReturnInstruction(op, expr->id());
7539 return true; 7525 return true;
7540 } 7526 }
7541 break; 7527 break;
7542 case kMathPow: 7528 case kMathPow:
7543 if (argument_count == 3) { 7529 if (argument_count == 3) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
7622 7608
7623 length_checker.Else(); 7609 length_checker.Else();
7624 HValue* elements = AddLoadElements(checked_object); 7610 HValue* elements = AddLoadElements(checked_object);
7625 // Ensure that we aren't popping from a copy-on-write array. 7611 // Ensure that we aren't popping from a copy-on-write array.
7626 if (IsFastSmiOrObjectElementsKind(elements_kind)) { 7612 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
7627 elements = BuildCopyElementsOnWrite(checked_object, elements, 7613 elements = BuildCopyElementsOnWrite(checked_object, elements,
7628 elements_kind, length); 7614 elements_kind, length);
7629 } 7615 }
7630 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1()); 7616 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
7631 result = AddElementAccess(elements, reduced_length, NULL, 7617 result = AddElementAccess(elements, reduced_length, NULL,
7632 bounds_check, elements_kind, LOAD); 7618 bounds_check, elements_kind, false);
7633 Factory* factory = isolate()->factory(); 7619 Factory* factory = isolate()->factory();
7634 double nan_double = FixedDoubleArray::hole_nan_as_double(); 7620 double nan_double = FixedDoubleArray::hole_nan_as_double();
7635 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) 7621 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
7636 ? Add<HConstant>(factory->the_hole_value()) 7622 ? Add<HConstant>(factory->the_hole_value())
7637 : Add<HConstant>(nan_double); 7623 : Add<HConstant>(nan_double);
7638 if (IsFastSmiOrObjectElementsKind(elements_kind)) { 7624 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
7639 elements_kind = FAST_HOLEY_ELEMENTS; 7625 elements_kind = FAST_HOLEY_ELEMENTS;
7640 } 7626 }
7641 AddElementAccess( 7627 AddElementAccess(
7642 elements, reduced_length, hole, bounds_check, elements_kind, STORE); 7628 elements, reduced_length, hole, bounds_check, elements_kind, true);
7643 Add<HStoreNamedField>( 7629 Add<HStoreNamedField>(
7644 checked_object, HObjectAccess::ForArrayLength(elements_kind), 7630 checked_object, HObjectAccess::ForArrayLength(elements_kind),
7645 reduced_length, STORE_TO_INITIALIZED_ENTRY); 7631 reduced_length, STORE_TO_INITIALIZED_ENTRY);
7646 7632
7647 if (!ast_context()->IsEffect()) Push(result); 7633 if (!ast_context()->IsEffect()) Push(result);
7648 7634
7649 length_checker.End(); 7635 length_checker.End();
7650 } 7636 }
7651 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); 7637 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
7652 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 7638 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
7777 receiver_maps->first(), &holder_lookup); 7763 receiver_maps->first(), &holder_lookup);
7778 if (holder_lookup == CallOptimization::kHolderNotFound) return false; 7764 if (holder_lookup == CallOptimization::kHolderNotFound) return false;
7779 7765
7780 if (FLAG_trace_inlining) { 7766 if (FLAG_trace_inlining) {
7781 PrintF("Inlining api function "); 7767 PrintF("Inlining api function ");
7782 function->ShortPrint(); 7768 function->ShortPrint();
7783 PrintF("\n"); 7769 PrintF("\n");
7784 } 7770 }
7785 7771
7786 bool drop_extra = false; 7772 bool drop_extra = false;
7787 bool is_store = false;
7788 switch (call_type) { 7773 switch (call_type) {
7789 case kCallApiFunction: 7774 case kCallApiFunction:
7790 case kCallApiMethod: 7775 case kCallApiMethod:
7791 // Need to check that none of the receiver maps could have changed. 7776 // Need to check that none of the receiver maps could have changed.
7792 Add<HCheckMaps>(receiver, receiver_maps, top_info()); 7777 Add<HCheckMaps>(receiver, receiver_maps);
7793 // Need to ensure the chain between receiver and api_holder is intact. 7778 // Need to ensure the chain between receiver and api_holder is intact.
7794 if (holder_lookup == CallOptimization::kHolderFound) { 7779 if (holder_lookup == CallOptimization::kHolderFound) {
7795 AddCheckPrototypeMaps(api_holder, receiver_maps->first()); 7780 AddCheckPrototypeMaps(api_holder, receiver_maps->first());
7796 } else { 7781 } else {
7797 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); 7782 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
7798 } 7783 }
7799 // Includes receiver. 7784 // Includes receiver.
7800 PushArgumentsFromEnvironment(argc + 1); 7785 PushArgumentsFromEnvironment(argc + 1);
7801 // Drop function after call. 7786 // Drop function after call.
7802 drop_extra = true; 7787 drop_extra = true;
7803 break; 7788 break;
7804 case kCallApiGetter: 7789 case kCallApiGetter:
7805 // Receiver and prototype chain cannot have changed. 7790 // Receiver and prototype chain cannot have changed.
7806 ASSERT_EQ(0, argc); 7791 ASSERT_EQ(0, argc);
7807 ASSERT_EQ(NULL, receiver); 7792 ASSERT_EQ(NULL, receiver);
7808 // Receiver is on expression stack. 7793 // Receiver is on expression stack.
7809 receiver = Pop(); 7794 receiver = Pop();
7810 Add<HPushArgument>(receiver); 7795 Add<HPushArgument>(receiver);
7811 break; 7796 break;
7812 case kCallApiSetter: 7797 case kCallApiSetter:
7813 { 7798 {
7814 is_store = true;
7815 // Receiver and prototype chain cannot have changed. 7799 // Receiver and prototype chain cannot have changed.
7816 ASSERT_EQ(1, argc); 7800 ASSERT_EQ(1, argc);
7817 ASSERT_EQ(NULL, receiver); 7801 ASSERT_EQ(NULL, receiver);
7818 // Receiver and value are on expression stack. 7802 // Receiver and value are on expression stack.
7819 HValue* value = Pop(); 7803 HValue* value = Pop();
7820 receiver = Pop(); 7804 receiver = Pop();
7821 Add<HPushArgument>(receiver); 7805 Add<HPushArgument>(receiver);
7822 Add<HPushArgument>(value); 7806 Add<HPushArgument>(value);
7823 break; 7807 break;
7824 } 7808 }
(...skipping 25 matching lines...) Expand all
7850 Add<HConstant>(function), 7834 Add<HConstant>(function),
7851 call_data, 7835 call_data,
7852 holder, 7836 holder,
7853 api_function_address, 7837 api_function_address,
7854 context() 7838 context()
7855 }; 7839 };
7856 7840
7857 CallInterfaceDescriptor* descriptor = 7841 CallInterfaceDescriptor* descriptor =
7858 isolate()->call_descriptor(Isolate::ApiFunctionCall); 7842 isolate()->call_descriptor(Isolate::ApiFunctionCall);
7859 7843
7860 CallApiFunctionStub stub(is_store, call_data_is_undefined, argc); 7844 CallApiFunctionStub stub(true, call_data_is_undefined, argc);
7861 Handle<Code> code = stub.GetCode(isolate()); 7845 Handle<Code> code = stub.GetCode(isolate());
7862 HConstant* code_value = Add<HConstant>(code); 7846 HConstant* code_value = Add<HConstant>(code);
7863 7847
7864 ASSERT((sizeof(op_vals) / kPointerSize) == 7848 ASSERT((sizeof(op_vals) / kPointerSize) ==
7865 descriptor->environment_length()); 7849 descriptor->environment_length());
7866 7850
7867 HInstruction* call = New<HCallWithDescriptor>( 7851 HInstruction* call = New<HCallWithDescriptor>(
7868 code_value, argc + 1, descriptor, 7852 code_value, argc + 1, descriptor,
7869 Vector<HValue*>(op_vals, descriptor->environment_length())); 7853 Vector<HValue*>(op_vals, descriptor->environment_length()));
7870 7854
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
7988 7972
7989 HValue* key = NULL; 7973 HValue* key = NULL;
7990 if (!prop->key()->IsPropertyName()) { 7974 if (!prop->key()->IsPropertyName()) {
7991 CHECK_ALIVE(VisitForValue(prop->key())); 7975 CHECK_ALIVE(VisitForValue(prop->key()));
7992 key = Pop(); 7976 key = Pop();
7993 } 7977 }
7994 7978
7995 CHECK_ALIVE(PushLoad(prop, receiver, key)); 7979 CHECK_ALIVE(PushLoad(prop, receiver, key));
7996 HValue* function = Pop(); 7980 HValue* function = Pop();
7997 7981
7998 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
7999
8000 // Push the function under the receiver. 7982 // Push the function under the receiver.
8001 environment()->SetExpressionStackAt(0, function); 7983 environment()->SetExpressionStackAt(0, function);
8002 7984
8003 Push(receiver); 7985 Push(receiver);
8004 7986
8005 if (function->IsConstant() && 7987 if (function->IsConstant() &&
8006 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { 7988 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8007 Handle<JSFunction> known_function = Handle<JSFunction>::cast( 7989 Handle<JSFunction> known_function = Handle<JSFunction>::cast(
8008 HConstant::cast(function)->handle(isolate())); 7990 HConstant::cast(function)->handle(isolate()));
8009 expr->set_target(known_function); 7991 expr->set_target(known_function);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
8052 } 8034 }
8053 8035
8054 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 8036 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
8055 if (global_call) { 8037 if (global_call) {
8056 Variable* var = proxy->var(); 8038 Variable* var = proxy->var();
8057 bool known_global_function = false; 8039 bool known_global_function = false;
8058 // If there is a global property cell for the name at compile time and 8040 // If there is a global property cell for the name at compile time and
8059 // access check is not enabled we assume that the function will not change 8041 // access check is not enabled we assume that the function will not change
8060 // and generate optimized code for calling the function. 8042 // and generate optimized code for calling the function.
8061 LookupResult lookup(isolate()); 8043 LookupResult lookup(isolate());
8062 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD); 8044 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
8063 if (type == kUseCell && 8045 if (type == kUseCell &&
8064 !current_info()->global_object()->IsAccessCheckNeeded()) { 8046 !current_info()->global_object()->IsAccessCheckNeeded()) {
8065 Handle<GlobalObject> global(current_info()->global_object()); 8047 Handle<GlobalObject> global(current_info()->global_object());
8066 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 8048 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
8067 } 8049 }
8068 CHECK_ALIVE(VisitForValue(expr->expression())); 8050 CHECK_ALIVE(VisitForValue(expr->expression()));
8069 HValue* function = Top(); 8051 HValue* function = Top();
8070 if (known_global_function) { 8052 if (known_global_function) {
8071 Add<HCheckValue>(function, expr->target()); 8053 Add<HCheckValue>(function, expr->target());
8072 8054
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
8262 TraceInline(target, caller, NULL); 8244 TraceInline(target, caller, NULL);
8263 } 8245 }
8264 return inline_ok; 8246 return inline_ok;
8265 } 8247 }
8266 8248
8267 8249
8268 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 8250 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
8269 ASSERT(!HasStackOverflow()); 8251 ASSERT(!HasStackOverflow());
8270 ASSERT(current_block() != NULL); 8252 ASSERT(current_block() != NULL);
8271 ASSERT(current_block()->HasPredecessor()); 8253 ASSERT(current_block()->HasPredecessor());
8272 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); 8254 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
8273 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 8255 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
8274 Factory* factory = isolate()->factory(); 8256 Factory* factory = isolate()->factory();
8275 8257
8276 // The constructor function is on the stack in the unoptimized code 8258 // The constructor function is on the stack in the unoptimized code
8277 // during evaluation of the arguments. 8259 // during evaluation of the arguments.
8278 CHECK_ALIVE(VisitForValue(expr->expression())); 8260 CHECK_ALIVE(VisitForValue(expr->expression()));
8279 HValue* function = Top(); 8261 HValue* function = Top();
8280 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8262 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8281 8263
8282 if (FLAG_inline_construct && 8264 if (FLAG_inline_construct &&
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
8805 if (key != NULL) Push(key); 8787 if (key != NULL) Push(key);
8806 Push(value); 8788 Push(value);
8807 BuildStore(expr, prop, ast_id, return_id); 8789 BuildStore(expr, prop, ast_id, return_id);
8808 } 8790 }
8809 8791
8810 8792
8811 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { 8793 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
8812 ASSERT(!HasStackOverflow()); 8794 ASSERT(!HasStackOverflow());
8813 ASSERT(current_block() != NULL); 8795 ASSERT(current_block() != NULL);
8814 ASSERT(current_block()->HasPredecessor()); 8796 ASSERT(current_block()->HasPredecessor());
8815 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); 8797 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
8816 Expression* target = expr->expression(); 8798 Expression* target = expr->expression();
8817 VariableProxy* proxy = target->AsVariableProxy(); 8799 VariableProxy* proxy = target->AsVariableProxy();
8818 Property* prop = target->AsProperty(); 8800 Property* prop = target->AsProperty();
8819 if (proxy == NULL && prop == NULL) { 8801 if (proxy == NULL && prop == NULL) {
8820 return Bailout(kInvalidLhsInCountOperation); 8802 return Bailout(kInvalidLhsInCountOperation);
8821 } 8803 }
8822 8804
8823 // Match the full code generator stack by simulating an extra stack 8805 // Match the full code generator stack by simulating an extra stack
8824 // element for postfix operations in a non-effect context. The return 8806 // element for postfix operations in a non-effect context. The return
8825 // value is ToNumber(input). 8807 // value is ToNumber(input).
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
9081 : HAllocationMode(allocation_site)) 9063 : HAllocationMode(allocation_site))
9082 : HAllocationMode(pretenure_flag); 9064 : HAllocationMode(pretenure_flag);
9083 9065
9084 HValue* result = HGraphBuilder::BuildBinaryOperation( 9066 HValue* result = HGraphBuilder::BuildBinaryOperation(
9085 expr->op(), left, right, left_type, right_type, result_type, 9067 expr->op(), left, right, left_type, right_type, result_type,
9086 fixed_right_arg, allocation_mode); 9068 fixed_right_arg, allocation_mode);
9087 // Add a simulate after instructions with observable side effects, and 9069 // Add a simulate after instructions with observable side effects, and
9088 // after phis, which are the result of BuildBinaryOperation when we 9070 // after phis, which are the result of BuildBinaryOperation when we
9089 // inlined some complex subgraph. 9071 // inlined some complex subgraph.
9090 if (result->HasObservableSideEffects() || result->IsPhi()) { 9072 if (result->HasObservableSideEffects() || result->IsPhi()) {
9091 if (push_sim_result == PUSH_BEFORE_SIMULATE) { 9073 if (push_sim_result == NO_PUSH_BEFORE_SIMULATE) {
9074 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
9075 } else {
9076 ASSERT(push_sim_result == PUSH_BEFORE_SIMULATE);
9092 Push(result); 9077 Push(result);
9093 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 9078 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
9094 Drop(1); 9079 Drop(1);
9095 } else {
9096 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
9097 } 9080 }
9098 } 9081 }
9099 return result; 9082 return result;
9100 } 9083 }
9101 9084
9102 9085
9103 HValue* HGraphBuilder::BuildBinaryOperation( 9086 HValue* HGraphBuilder::BuildBinaryOperation(
9104 Token::Value op, 9087 Token::Value op,
9105 HValue* left, 9088 HValue* left,
9106 HValue* right, 9089 HValue* right,
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
9471 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { 9454 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
9472 CHECK_ALIVE(VisitForValue(expr->left())); 9455 CHECK_ALIVE(VisitForValue(expr->left()));
9473 CHECK_ALIVE(VisitForValue(expr->right())); 9456 CHECK_ALIVE(VisitForValue(expr->right()));
9474 SetSourcePosition(expr->position()); 9457 SetSourcePosition(expr->position());
9475 HValue* right = Pop(); 9458 HValue* right = Pop();
9476 HValue* left = Pop(); 9459 HValue* left = Pop();
9477 HValue* result = 9460 HValue* result =
9478 BuildBinaryOperation(expr, left, right, 9461 BuildBinaryOperation(expr, left, right,
9479 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE 9462 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
9480 : PUSH_BEFORE_SIMULATE); 9463 : PUSH_BEFORE_SIMULATE);
9481 if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) { 9464 if (FLAG_emit_opt_code_positions && result->IsBinaryOperation()) {
9482 HBinaryOperation::cast(result)->SetOperandPositions( 9465 HBinaryOperation::cast(result)->SetOperandPositions(
9483 zone(), 9466 zone(), expr->left()->position(), expr->right()->position());
9484 ScriptPositionToSourcePosition(expr->left()->position()),
9485 ScriptPositionToSourcePosition(expr->right()->position()));
9486 } 9467 }
9487 return ast_context()->ReturnValue(result); 9468 return ast_context()->ReturnValue(result);
9488 } 9469 }
9489 9470
9490 9471
9491 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 9472 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
9492 Expression* sub_expr, 9473 Expression* sub_expr,
9493 Handle<String> check) { 9474 Handle<String> check) {
9494 CHECK_ALIVE(VisitForTypeOf(sub_expr)); 9475 CHECK_ALIVE(VisitForTypeOf(sub_expr));
9495 SetSourcePosition(expr->position()); 9476 SetSourcePosition(expr->position());
(...skipping 13 matching lines...) Expand all
9509 (right->IsConstant() && 9490 (right->IsConstant() &&
9510 HConstant::cast(right)->handle(isolate)->IsBoolean())); 9491 HConstant::cast(right)->handle(isolate)->IsBoolean()));
9511 } 9492 }
9512 9493
9513 9494
9514 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 9495 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
9515 ASSERT(!HasStackOverflow()); 9496 ASSERT(!HasStackOverflow());
9516 ASSERT(current_block() != NULL); 9497 ASSERT(current_block() != NULL);
9517 ASSERT(current_block()->HasPredecessor()); 9498 ASSERT(current_block()->HasPredecessor());
9518 9499
9519 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); 9500 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
9520 9501
9521 // Check for a few fast cases. The AST visiting behavior must be in sync 9502 // Check for a few fast cases. The AST visiting behavior must be in sync
9522 // with the full codegen: We don't push both left and right values onto 9503 // with the full codegen: We don't push both left and right values onto
9523 // the expression stack when one side is a special-case literal. 9504 // the expression stack when one side is a special-case literal.
9524 Expression* sub_expr = NULL; 9505 Expression* sub_expr = NULL;
9525 Handle<String> check; 9506 Handle<String> check;
9526 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { 9507 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
9527 return HandleLiteralCompareTypeof(expr, sub_expr, check); 9508 return HandleLiteralCompareTypeof(expr, sub_expr, check);
9528 } 9509 }
9529 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { 9510 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
(...skipping 14 matching lines...) Expand all
9544 return ast_context()->ReturnControl(instr, expr->id()); 9525 return ast_context()->ReturnControl(instr, expr->id());
9545 } 9526 }
9546 9527
9547 Type* left_type = expr->left()->bounds().lower; 9528 Type* left_type = expr->left()->bounds().lower;
9548 Type* right_type = expr->right()->bounds().lower; 9529 Type* right_type = expr->right()->bounds().lower;
9549 Type* combined_type = expr->combined_type(); 9530 Type* combined_type = expr->combined_type();
9550 9531
9551 CHECK_ALIVE(VisitForValue(expr->left())); 9532 CHECK_ALIVE(VisitForValue(expr->left()));
9552 CHECK_ALIVE(VisitForValue(expr->right())); 9533 CHECK_ALIVE(VisitForValue(expr->right()));
9553 9534
9554 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); 9535 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
9555 9536
9556 HValue* right = Pop(); 9537 HValue* right = Pop();
9557 HValue* left = Pop(); 9538 HValue* left = Pop();
9558 Token::Value op = expr->op(); 9539 Token::Value op = expr->op();
9559 9540
9560 if (IsLiteralCompareBool(isolate(), left, op, right)) { 9541 if (IsLiteralCompareBool(isolate(), left, op, right)) {
9561 HCompareObjectEqAndBranch* result = 9542 HCompareObjectEqAndBranch* result =
9562 New<HCompareObjectEqAndBranch>(left, right); 9543 New<HCompareObjectEqAndBranch>(left, right);
9563 return ast_context()->ReturnControl(result, expr->id()); 9544 return ast_context()->ReturnControl(result, expr->id());
9564 } 9545 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
9604 } else if (op == Token::IN) { 9585 } else if (op == Token::IN) {
9605 HValue* function = AddLoadJSBuiltin(Builtins::IN); 9586 HValue* function = AddLoadJSBuiltin(Builtins::IN);
9606 Add<HPushArgument>(left); 9587 Add<HPushArgument>(left);
9607 Add<HPushArgument>(right); 9588 Add<HPushArgument>(right);
9608 // TODO(olivf) InvokeFunction produces a check for the parameter count, 9589 // TODO(olivf) InvokeFunction produces a check for the parameter count,
9609 // even though we are certain to pass the correct number of arguments here. 9590 // even though we are certain to pass the correct number of arguments here.
9610 HInstruction* result = New<HInvokeFunction>(function, 2); 9591 HInstruction* result = New<HInvokeFunction>(function, 2);
9611 return ast_context()->ReturnInstruction(result, expr->id()); 9592 return ast_context()->ReturnInstruction(result, expr->id());
9612 } 9593 }
9613 9594
9614 PushBeforeSimulateBehavior push_behavior =
9615 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
9616 : PUSH_BEFORE_SIMULATE;
9617 HControlInstruction* compare = BuildCompareInstruction( 9595 HControlInstruction* compare = BuildCompareInstruction(
9618 op, left, right, left_type, right_type, combined_type, 9596 op, left, right, left_type, right_type, combined_type,
9619 ScriptPositionToSourcePosition(expr->left()->position()), 9597 expr->left()->position(), expr->right()->position(), expr->id());
9620 ScriptPositionToSourcePosition(expr->right()->position()),
9621 push_behavior, expr->id());
9622 if (compare == NULL) return; // Bailed out. 9598 if (compare == NULL) return; // Bailed out.
9623 return ast_context()->ReturnControl(compare, expr->id()); 9599 return ast_context()->ReturnControl(compare, expr->id());
9624 } 9600 }
9625 9601
9626 9602
9627 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( 9603 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
9628 Token::Value op, 9604 Token::Value op,
9629 HValue* left, 9605 HValue* left,
9630 HValue* right, 9606 HValue* right,
9631 Type* left_type, 9607 Type* left_type,
9632 Type* right_type, 9608 Type* right_type,
9633 Type* combined_type, 9609 Type* combined_type,
9634 HSourcePosition left_position, 9610 int left_position,
9635 HSourcePosition right_position, 9611 int right_position,
9636 PushBeforeSimulateBehavior push_sim_result,
9637 BailoutId bailout_id) { 9612 BailoutId bailout_id) {
9638 // Cases handled below depend on collected type feedback. They should 9613 // Cases handled below depend on collected type feedback. They should
9639 // soft deoptimize when there is no type feedback. 9614 // soft deoptimize when there is no type feedback.
9640 if (combined_type->Is(Type::None())) { 9615 if (combined_type->Is(Type::None())) {
9641 Add<HDeoptimize>("Insufficient type feedback for combined type " 9616 Add<HDeoptimize>("Insufficient type feedback for combined type "
9642 "of binary operation", 9617 "of binary operation",
9643 Deoptimizer::SOFT); 9618 Deoptimizer::SOFT);
9644 combined_type = left_type = right_type = Type::Any(zone()); 9619 combined_type = left_type = right_type = Type::Any(zone());
9645 } 9620 }
9646 9621
9647 Representation left_rep = Representation::FromType(left_type); 9622 Representation left_rep = Representation::FromType(left_type);
9648 Representation right_rep = Representation::FromType(right_type); 9623 Representation right_rep = Representation::FromType(right_type);
9649 Representation combined_rep = Representation::FromType(combined_type); 9624 Representation combined_rep = Representation::FromType(combined_type);
9650 9625
9651 if (combined_type->Is(Type::Receiver())) { 9626 if (combined_type->Is(Type::Receiver())) {
9652 if (Token::IsEqualityOp(op)) { 9627 if (Token::IsEqualityOp(op)) {
9653 // Can we get away with map check and not instance type check? 9628 // Can we get away with map check and not instance type check?
9654 HValue* operand_to_check = 9629 HValue* operand_to_check =
9655 left->block()->block_id() < right->block()->block_id() ? left : right; 9630 left->block()->block_id() < right->block()->block_id() ? left : right;
9656 if (combined_type->IsClass()) { 9631 if (combined_type->IsClass()) {
9657 Handle<Map> map = combined_type->AsClass(); 9632 Handle<Map> map = combined_type->AsClass();
9658 AddCheckMap(operand_to_check, map); 9633 AddCheckMap(operand_to_check, map);
9659 HCompareObjectEqAndBranch* result = 9634 HCompareObjectEqAndBranch* result =
9660 New<HCompareObjectEqAndBranch>(left, right); 9635 New<HCompareObjectEqAndBranch>(left, right);
9661 if (FLAG_hydrogen_track_positions) { 9636 if (FLAG_emit_opt_code_positions) {
9662 result->set_operand_position(zone(), 0, left_position); 9637 result->set_operand_position(zone(), 0, left_position);
9663 result->set_operand_position(zone(), 1, right_position); 9638 result->set_operand_position(zone(), 1, right_position);
9664 } 9639 }
9665 return result; 9640 return result;
9666 } else { 9641 } else {
9667 BuildCheckHeapObject(operand_to_check); 9642 BuildCheckHeapObject(operand_to_check);
9668 Add<HCheckInstanceType>(operand_to_check, 9643 Add<HCheckInstanceType>(operand_to_check,
9669 HCheckInstanceType::IS_SPEC_OBJECT); 9644 HCheckInstanceType::IS_SPEC_OBJECT);
9670 HCompareObjectEqAndBranch* result = 9645 HCompareObjectEqAndBranch* result =
9671 New<HCompareObjectEqAndBranch>(left, right); 9646 New<HCompareObjectEqAndBranch>(left, right);
(...skipping 19 matching lines...) Expand all
9691 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING); 9666 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
9692 HStringCompareAndBranch* result = 9667 HStringCompareAndBranch* result =
9693 New<HStringCompareAndBranch>(left, right, op); 9668 New<HStringCompareAndBranch>(left, right, op);
9694 return result; 9669 return result;
9695 } else { 9670 } else {
9696 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 9671 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
9697 HCompareGeneric* result = Add<HCompareGeneric>(left, right, op); 9672 HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
9698 result->set_observed_input_representation(1, left_rep); 9673 result->set_observed_input_representation(1, left_rep);
9699 result->set_observed_input_representation(2, right_rep); 9674 result->set_observed_input_representation(2, right_rep);
9700 if (result->HasObservableSideEffects()) { 9675 if (result->HasObservableSideEffects()) {
9701 if (push_sim_result == PUSH_BEFORE_SIMULATE) { 9676 Push(result);
9702 Push(result); 9677 AddSimulate(bailout_id, REMOVABLE_SIMULATE);
9703 AddSimulate(bailout_id, REMOVABLE_SIMULATE); 9678 Drop(1);
9704 Drop(1);
9705 } else {
9706 AddSimulate(bailout_id, REMOVABLE_SIMULATE);
9707 }
9708 } 9679 }
9709 // TODO(jkummerow): Can we make this more efficient? 9680 // TODO(jkummerow): Can we make this more efficient?
9710 HBranch* branch = New<HBranch>(result); 9681 HBranch* branch = New<HBranch>(result);
9711 return branch; 9682 return branch;
9712 } else { 9683 } else {
9713 HCompareNumericAndBranch* result = 9684 HCompareNumericAndBranch* result =
9714 New<HCompareNumericAndBranch>(left, right, op); 9685 New<HCompareNumericAndBranch>(left, right, op);
9715 result->set_observed_input_representation(left_rep, right_rep); 9686 result->set_observed_input_representation(left_rep, right_rep);
9716 if (FLAG_hydrogen_track_positions) { 9687 if (FLAG_emit_opt_code_positions) {
9717 result->SetOperandPositions(zone(), left_position, right_position); 9688 result->SetOperandPositions(zone(), left_position, right_position);
9718 } 9689 }
9719 return result; 9690 return result;
9720 } 9691 }
9721 } 9692 }
9722 } 9693 }
9723 9694
9724 9695
9725 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 9696 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
9726 Expression* sub_expr, 9697 Expression* sub_expr,
9727 NilValue nil) { 9698 NilValue nil) {
9728 ASSERT(!HasStackOverflow()); 9699 ASSERT(!HasStackOverflow());
9729 ASSERT(current_block() != NULL); 9700 ASSERT(current_block() != NULL);
9730 ASSERT(current_block()->HasPredecessor()); 9701 ASSERT(current_block()->HasPredecessor());
9731 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); 9702 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
9732 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); 9703 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
9733 CHECK_ALIVE(VisitForValue(sub_expr)); 9704 CHECK_ALIVE(VisitForValue(sub_expr));
9734 HValue* value = Pop(); 9705 HValue* value = Pop();
9735 if (expr->op() == Token::EQ_STRICT) { 9706 if (expr->op() == Token::EQ_STRICT) {
9736 HConstant* nil_constant = nil == kNullValue 9707 HConstant* nil_constant = nil == kNullValue
9737 ? graph()->GetConstantNull() 9708 ? graph()->GetConstantNull()
9738 : graph()->GetConstantUndefined(); 9709 : graph()->GetConstantUndefined();
9739 HCompareObjectEqAndBranch* instr = 9710 HCompareObjectEqAndBranch* instr =
9740 New<HCompareObjectEqAndBranch>(value, nil_constant); 9711 New<HCompareObjectEqAndBranch>(value, nil_constant);
9741 return ast_context()->ReturnControl(instr, expr->id()); 9712 return ast_context()->ReturnControl(instr, expr->id());
9742 } else { 9713 } else {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
9917 // 1) it's a child object of another object with a valid allocation site 9888 // 1) it's a child object of another object with a valid allocation site
9918 // 2) we can just use the mode of the parent object for pretenuring 9889 // 2) we can just use the mode of the parent object for pretenuring
9919 HInstruction* double_box = 9890 HInstruction* double_box =
9920 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), 9891 Add<HAllocate>(heap_number_constant, HType::HeapNumber(),
9921 pretenure_flag, HEAP_NUMBER_TYPE); 9892 pretenure_flag, HEAP_NUMBER_TYPE);
9922 AddStoreMapConstant(double_box, 9893 AddStoreMapConstant(double_box,
9923 isolate()->factory()->heap_number_map()); 9894 isolate()->factory()->heap_number_map());
9924 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), 9895 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
9925 Add<HConstant>(value)); 9896 Add<HConstant>(value));
9926 value_instruction = double_box; 9897 value_instruction = double_box;
9927 } else if (representation.IsSmi()) { 9898 } else if (representation.IsSmi() && value->IsUninitialized()) {
9928 value_instruction = value->IsUninitialized() 9899 value_instruction = graph()->GetConstant0();
9929 ? graph()->GetConstant0()
9930 : Add<HConstant>(value);
9931 // Ensure that value is stored as smi.
9932 access = access.WithRepresentation(representation);
9933 } else { 9900 } else {
9934 value_instruction = Add<HConstant>(value); 9901 value_instruction = Add<HConstant>(value);
9935 } 9902 }
9936 9903
9937 Add<HStoreNamedField>(object, access, value_instruction); 9904 Add<HStoreNamedField>(object, access, value_instruction);
9938 } 9905 }
9939 } 9906 }
9940 9907
9941 int inobject_properties = boilerplate_object->map()->inobject_properties(); 9908 int inobject_properties = boilerplate_object->map()->inobject_properties();
9942 HInstruction* value_instruction = 9909 HInstruction* value_instruction =
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
10355 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10322 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10356 HValue* date = Pop(); 10323 HValue* date = Pop();
10357 HDateField* result = New<HDateField>(date, index); 10324 HDateField* result = New<HDateField>(date, index);
10358 return ast_context()->ReturnInstruction(result, call->id()); 10325 return ast_context()->ReturnInstruction(result, call->id());
10359 } 10326 }
10360 10327
10361 10328
10362 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( 10329 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
10363 CallRuntime* call) { 10330 CallRuntime* call) {
10364 ASSERT(call->arguments()->length() == 3); 10331 ASSERT(call->arguments()->length() == 3);
10365 // We need to follow the evaluation order of full codegen. 10332 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10366 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10333 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10367 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 10334 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
10368 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10369 HValue* string = Pop();
10370 HValue* value = Pop(); 10335 HValue* value = Pop();
10371 HValue* index = Pop(); 10336 HValue* index = Pop();
10337 HValue* string = Pop();
10372 Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string, 10338 Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
10373 index, value); 10339 index, value);
10374 Add<HSimulate>(call->id(), FIXED_SIMULATE); 10340 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10375 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 10341 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10376 } 10342 }
10377 10343
10378 10344
10379 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( 10345 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
10380 CallRuntime* call) { 10346 CallRuntime* call) {
10381 ASSERT(call->arguments()->length() == 3); 10347 ASSERT(call->arguments()->length() == 3);
10382 // We need to follow the evaluation order of full codegen. 10348 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10383 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10349 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10384 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 10350 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
10385 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10386 HValue* string = Pop();
10387 HValue* value = Pop(); 10351 HValue* value = Pop();
10388 HValue* index = Pop(); 10352 HValue* index = Pop();
10353 HValue* string = Pop();
10389 Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string, 10354 Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
10390 index, value); 10355 index, value);
10391 Add<HSimulate>(call->id(), FIXED_SIMULATE); 10356 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10392 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 10357 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10393 } 10358 }
10394 10359
10395 10360
10396 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 10361 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
10397 ASSERT(call->arguments()->length() == 2); 10362 ASSERT(call->arguments()->length() == 2);
10398 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10363 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10399 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10364 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10400 HValue* value = Pop(); 10365 HValue* value = Pop();
10401 HValue* object = Pop(); 10366 HValue* object = Pop();
10402 10367
10403 // Check if object is a JSValue. 10368 // Check if object is a JSValue.
10404 IfBuilder if_objectisvalue(this); 10369 IfBuilder if_objectisvalue(this);
10405 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); 10370 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
10406 if_objectisvalue.Then(); 10371 if_objectisvalue.Then();
10407 { 10372 {
10408 // Create in-object property store to kValueOffset. 10373 // Create in-object property store to kValueOffset.
10409 Add<HStoreNamedField>(object, 10374 Add<HStoreNamedField>(object,
10410 HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset), 10375 HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
10411 value); 10376 value);
10412 if (!ast_context()->IsEffect()) {
10413 Push(value);
10414 }
10415 Add<HSimulate>(call->id(), FIXED_SIMULATE); 10377 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10416 } 10378 }
10417 if_objectisvalue.Else(); 10379 if_objectisvalue.Else();
10418 { 10380 {
10419 // Nothing to do in this case. 10381 // Nothing to do in this case.
10420 if (!ast_context()->IsEffect()) {
10421 Push(value);
10422 }
10423 Add<HSimulate>(call->id(), FIXED_SIMULATE); 10382 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10424 } 10383 }
10425 if_objectisvalue.End(); 10384 if_objectisvalue.End();
10426 if (!ast_context()->IsEffect()) {
10427 Drop(1);
10428 }
10429 return ast_context()->ReturnValue(value); 10385 return ast_context()->ReturnValue(value);
10430 } 10386 }
10431 10387
10432 10388
10433 // Fast support for charCodeAt(n). 10389 // Fast support for charCodeAt(n).
10434 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 10390 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
10435 ASSERT(call->arguments()->length() == 2); 10391 ASSERT(call->arguments()->length() == 2);
10436 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10392 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10437 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10393 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10438 HValue* index = Pop(); 10394 HValue* index = Pop();
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
10961 PrintTo(&trace); 10917 PrintTo(&trace);
10962 PrintF("%s", trace.ToCString().get()); 10918 PrintF("%s", trace.ToCString().get());
10963 } 10919 }
10964 10920
10965 10921
10966 void HTracer::TraceCompilation(CompilationInfo* info) { 10922 void HTracer::TraceCompilation(CompilationInfo* info) {
10967 Tag tag(this, "compilation"); 10923 Tag tag(this, "compilation");
10968 if (info->IsOptimizing()) { 10924 if (info->IsOptimizing()) {
10969 Handle<String> name = info->function()->debug_name(); 10925 Handle<String> name = info->function()->debug_name();
10970 PrintStringProperty("name", name->ToCString().get()); 10926 PrintStringProperty("name", name->ToCString().get());
10971 PrintIndent(); 10927 PrintStringProperty("method", name->ToCString().get());
10972 trace_.Add("method \"%s:%d\"\n",
10973 name->ToCString().get(),
10974 info->optimization_id());
10975 } else { 10928 } else {
10976 CodeStub::Major major_key = info->code_stub()->MajorKey(); 10929 CodeStub::Major major_key = info->code_stub()->MajorKey();
10977 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); 10930 PrintStringProperty("name", CodeStub::MajorName(major_key, false));
10978 PrintStringProperty("method", "stub"); 10931 PrintStringProperty("method", "stub");
10979 } 10932 }
10980 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 10933 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
10981 } 10934 }
10982 10935
10983 10936
10984 void HTracer::TraceLithium(const char* name, LChunk* chunk) { 10937 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
11078 trace_.Add(" "); 11031 trace_.Add(" ");
11079 phi->PrintTo(&trace_); 11032 phi->PrintTo(&trace_);
11080 trace_.Add("\n"); 11033 trace_.Add("\n");
11081 } 11034 }
11082 } 11035 }
11083 11036
11084 { 11037 {
11085 Tag HIR_tag(this, "HIR"); 11038 Tag HIR_tag(this, "HIR");
11086 for (HInstructionIterator it(current); !it.Done(); it.Advance()) { 11039 for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
11087 HInstruction* instruction = it.Current(); 11040 HInstruction* instruction = it.Current();
11041 int bci = FLAG_emit_opt_code_positions && instruction->has_position() ?
11042 instruction->position() : 0;
11088 int uses = instruction->UseCount(); 11043 int uses = instruction->UseCount();
11089 PrintIndent(); 11044 PrintIndent();
11090 trace_.Add("0 %d ", uses); 11045 trace_.Add("%d %d ", bci, uses);
11091 instruction->PrintNameTo(&trace_); 11046 instruction->PrintNameTo(&trace_);
11092 trace_.Add(" "); 11047 trace_.Add(" ");
11093 instruction->PrintTo(&trace_); 11048 instruction->PrintTo(&trace_);
11094 if (FLAG_hydrogen_track_positions &&
11095 instruction->has_position() &&
11096 instruction->position().raw() != 0) {
11097 const HSourcePosition pos = instruction->position();
11098 trace_.Add(" pos:");
11099 if (pos.inlining_id() != 0) {
11100 trace_.Add("%d_", pos.inlining_id());
11101 }
11102 trace_.Add("%d", pos.position());
11103 }
11104 trace_.Add(" <|@\n"); 11049 trace_.Add(" <|@\n");
11105 } 11050 }
11106 } 11051 }
11107 11052
11108 11053
11109 if (chunk != NULL) { 11054 if (chunk != NULL) {
11110 Tag LIR_tag(this, "LIR"); 11055 Tag LIR_tag(this, "LIR");
11111 int first_index = current->first_instruction_index(); 11056 int first_index = current->first_instruction_index();
11112 int last_index = current->last_instruction_index(); 11057 int last_index = current->last_instruction_index();
11113 if (first_index != -1 && last_index != -1) { 11058 if (first_index != -1 && last_index != -1) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
11294 if (ShouldProduceTraceOutput()) { 11239 if (ShouldProduceTraceOutput()) {
11295 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11240 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11296 } 11241 }
11297 11242
11298 #ifdef DEBUG 11243 #ifdef DEBUG
11299 graph_->Verify(false); // No full verify. 11244 graph_->Verify(false); // No full verify.
11300 #endif 11245 #endif
11301 } 11246 }
11302 11247
11303 } } // namespace v8::internal 11248 } } // 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