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

Side by Side Diff: src/hydrogen.cc

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
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"
71 #elif V8_TARGET_ARCH_ARM 73 #elif V8_TARGET_ARCH_ARM
72 #include "arm/lithium-codegen-arm.h" 74 #include "arm/lithium-codegen-arm.h"
73 #elif V8_TARGET_ARCH_MIPS 75 #elif V8_TARGET_ARCH_MIPS
74 #include "mips/lithium-codegen-mips.h" 76 #include "mips/lithium-codegen-mips.h"
75 #else 77 #else
76 #error Unsupported target architecture. 78 #error Unsupported target architecture.
77 #endif 79 #endif
78 80
79 namespace v8 { 81 namespace v8 {
80 namespace internal { 82 namespace internal {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 136
135 void HBasicBlock::RemovePhi(HPhi* phi) { 137 void HBasicBlock::RemovePhi(HPhi* phi) {
136 ASSERT(phi->block() == this); 138 ASSERT(phi->block() == this);
137 ASSERT(phis_.Contains(phi)); 139 ASSERT(phis_.Contains(phi));
138 phi->Kill(); 140 phi->Kill();
139 phis_.RemoveElement(phi); 141 phis_.RemoveElement(phi);
140 phi->SetBlock(NULL); 142 phi->SetBlock(NULL);
141 } 143 }
142 144
143 145
144 void HBasicBlock::AddInstruction(HInstruction* instr, int position) { 146 void HBasicBlock::AddInstruction(HInstruction* instr,
147 HSourcePosition position) {
145 ASSERT(!IsStartBlock() || !IsFinished()); 148 ASSERT(!IsStartBlock() || !IsFinished());
146 ASSERT(!instr->IsLinked()); 149 ASSERT(!instr->IsLinked());
147 ASSERT(!IsFinished()); 150 ASSERT(!IsFinished());
148 151
149 if (position != RelocInfo::kNoPosition) { 152 if (!position.IsUnknown()) {
150 instr->set_position(position); 153 instr->set_position(position);
151 } 154 }
152 if (first_ == NULL) { 155 if (first_ == NULL) {
153 ASSERT(last_environment() != NULL); 156 ASSERT(last_environment() != NULL);
154 ASSERT(!last_environment()->ast_id().IsNone()); 157 ASSERT(!last_environment()->ast_id().IsNone());
155 HBlockEntry* entry = new(zone()) HBlockEntry(); 158 HBlockEntry* entry = new(zone()) HBlockEntry();
156 entry->InitializeAsFirst(this); 159 entry->InitializeAsFirst(this);
157 if (position != RelocInfo::kNoPosition) { 160 if (!position.IsUnknown()) {
158 entry->set_position(position); 161 entry->set_position(position);
159 } else { 162 } else {
160 ASSERT(!FLAG_emit_opt_code_positions || 163 ASSERT(!FLAG_hydrogen_track_positions ||
161 !graph()->info()->IsOptimizing()); 164 !graph()->info()->IsOptimizing());
162 } 165 }
163 first_ = last_ = entry; 166 first_ = last_ = entry;
164 } 167 }
165 instr->InsertAfter(last_); 168 instr->InsertAfter(last_);
166 } 169 }
167 170
168 171
169 HPhi* HBasicBlock::AddNewPhi(int merged_index) { 172 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
170 if (graph()->IsInsideNoSideEffectsScope()) { 173 if (graph()->IsInsideNoSideEffectsScope()) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 !it.Done(); 206 !it.Done();
204 it.Advance()) { 207 it.Advance()) {
205 int index = it.Current(); 208 int index = it.Current();
206 instr->AddAssignedValue(index, environment->Lookup(index)); 209 instr->AddAssignedValue(index, environment->Lookup(index));
207 } 210 }
208 environment->ClearHistory(); 211 environment->ClearHistory();
209 return instr; 212 return instr;
210 } 213 }
211 214
212 215
213 void HBasicBlock::Finish(HControlInstruction* end, int position) { 216 void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) {
214 ASSERT(!IsFinished()); 217 ASSERT(!IsFinished());
215 AddInstruction(end, position); 218 AddInstruction(end, position);
216 end_ = end; 219 end_ = end;
217 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 220 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
218 it.Current()->RegisterPredecessor(this); 221 it.Current()->RegisterPredecessor(this);
219 } 222 }
220 } 223 }
221 224
222 225
223 void HBasicBlock::Goto(HBasicBlock* block, 226 void HBasicBlock::Goto(HBasicBlock* block,
224 int position, 227 HSourcePosition position,
225 FunctionState* state, 228 FunctionState* state,
226 bool add_simulate) { 229 bool add_simulate) {
227 bool drop_extra = state != NULL && 230 bool drop_extra = state != NULL &&
228 state->inlining_kind() == DROP_EXTRA_ON_RETURN; 231 state->inlining_kind() == NORMAL_RETURN;
229 232
230 if (block->IsInlineReturnTarget()) { 233 if (block->IsInlineReturnTarget()) {
231 HEnvironment* env = last_environment(); 234 HEnvironment* env = last_environment();
232 int argument_count = env->arguments_environment()->parameter_count(); 235 int argument_count = env->arguments_environment()->parameter_count();
233 AddInstruction(new(zone()) 236 AddInstruction(new(zone())
234 HLeaveInlined(state->entry(), argument_count), 237 HLeaveInlined(state->entry(), argument_count),
235 position); 238 position);
236 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 239 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
237 } 240 }
238 241
239 if (add_simulate) AddNewSimulate(BailoutId::None(), position); 242 if (add_simulate) AddNewSimulate(BailoutId::None(), position);
240 HGoto* instr = new(zone()) HGoto(block); 243 HGoto* instr = new(zone()) HGoto(block);
241 Finish(instr, position); 244 Finish(instr, position);
242 } 245 }
243 246
244 247
245 void HBasicBlock::AddLeaveInlined(HValue* return_value, 248 void HBasicBlock::AddLeaveInlined(HValue* return_value,
246 FunctionState* state, 249 FunctionState* state,
247 int position) { 250 HSourcePosition position) {
248 HBasicBlock* target = state->function_return(); 251 HBasicBlock* target = state->function_return();
249 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; 252 bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
250 253
251 ASSERT(target->IsInlineReturnTarget()); 254 ASSERT(target->IsInlineReturnTarget());
252 ASSERT(return_value != NULL); 255 ASSERT(return_value != NULL);
253 HEnvironment* env = last_environment(); 256 HEnvironment* env = last_environment();
254 int argument_count = env->arguments_environment()->parameter_count(); 257 int argument_count = env->arguments_environment()->parameter_count();
255 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), 258 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
256 position); 259 position);
257 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 260 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
258 last_environment()->Push(return_value); 261 last_environment()->Push(return_value);
259 AddNewSimulate(BailoutId::None(), position); 262 AddNewSimulate(BailoutId::None(), position);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 bool HBasicBlock::Dominates(HBasicBlock* other) const { 298 bool HBasicBlock::Dominates(HBasicBlock* other) const {
296 HBasicBlock* current = other->dominator(); 299 HBasicBlock* current = other->dominator();
297 while (current != NULL) { 300 while (current != NULL) {
298 if (current == this) return true; 301 if (current == this) return true;
299 current = current->dominator(); 302 current = current->dominator();
300 } 303 }
301 return false; 304 return false;
302 } 305 }
303 306
304 307
308 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
309 if (this == other) return true;
310 return Dominates(other);
311 }
312
313
305 int HBasicBlock::LoopNestingDepth() const { 314 int HBasicBlock::LoopNestingDepth() const {
306 const HBasicBlock* current = this; 315 const HBasicBlock* current = this;
307 int result = (current->IsLoopHeader()) ? 1 : 0; 316 int result = (current->IsLoopHeader()) ? 1 : 0;
308 while (current->parent_loop_header() != NULL) { 317 while (current->parent_loop_header() != NULL) {
309 current = current->parent_loop_header(); 318 current = current->parent_loop_header();
310 result++; 319 result++;
311 } 320 }
312 return result; 321 return result;
313 } 322 }
314 323
315 324
316 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) { 325 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
317 ASSERT(IsLoopHeader()); 326 ASSERT(IsLoopHeader());
318 327
319 SetJoinId(stmt->EntryId()); 328 SetJoinId(stmt->EntryId());
320 if (predecessors()->length() == 1) { 329 if (predecessors()->length() == 1) {
321 // This is a degenerated loop. 330 // This is a degenerated loop.
322 DetachLoopInformation(); 331 DetachLoopInformation();
323 return; 332 return;
324 } 333 }
325 334
326 // Only the first entry into the loop is from outside the loop. All other 335 // Only the first entry into the loop is from outside the loop. All other
327 // entries must be back edges. 336 // entries must be back edges.
328 for (int i = 1; i < predecessors()->length(); ++i) { 337 for (int i = 1; i < predecessors()->length(); ++i) {
329 loop_information()->RegisterBackEdge(predecessors()->at(i)); 338 loop_information()->RegisterBackEdge(predecessors()->at(i));
330 } 339 }
331 } 340 }
332 341
333 342
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
334 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { 352 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
335 if (HasPredecessor()) { 353 if (HasPredecessor()) {
336 // Only loop header blocks can have a predecessor added after 354 // Only loop header blocks can have a predecessor added after
337 // instructions have been added to the block (they have phis for all 355 // instructions have been added to the block (they have phis for all
338 // values in the environment, these phis may be eliminated later). 356 // values in the environment, these phis may be eliminated later).
339 ASSERT(IsLoopHeader() || first_ == NULL); 357 ASSERT(IsLoopHeader() || first_ == NULL);
340 HEnvironment* incoming_env = pred->last_environment(); 358 HEnvironment* incoming_env = pred->last_environment();
341 if (IsLoopHeader()) { 359 if (IsLoopHeader()) {
342 ASSERT(phis()->length() == incoming_env->length()); 360 ASSERT(phis()->length() == incoming_env->length());
343 for (int i = 0; i < phis_.length(); ++i) { 361 for (int i = 0; i < phis_.length(); ++i) {
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 } 1037 }
1020 builder_->GotoNoSimulate(current->block_, merge_block); 1038 builder_->GotoNoSimulate(current->block_, merge_block);
1021 } 1039 }
1022 current = current->next_; 1040 current = current->next_;
1023 } 1041 }
1024 1042
1025 // Merge deopt blocks, padding when necessary. 1043 // Merge deopt blocks, padding when necessary.
1026 current = merge_at_join_blocks_; 1044 current = merge_at_join_blocks_;
1027 while (current != NULL) { 1045 while (current != NULL) {
1028 if (current->deopt_ && current->block_ != NULL) { 1046 if (current->deopt_ && current->block_ != NULL) {
1029 builder_->PadEnvironmentForContinuation(current->block_, 1047 current->block_->FinishExit(
1030 merge_block); 1048 HAbnormalExit::New(builder_->zone(), NULL),
1031 builder_->GotoNoSimulate(current->block_, merge_block); 1049 HSourcePosition::Unknown());
1032 } 1050 }
1033 current = current->next_; 1051 current = current->next_;
1034 } 1052 }
1035 builder_->set_current_block(merge_block); 1053 builder_->set_current_block(merge_block);
1036 } 1054 }
1037 1055
1038 1056
1039 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 1057 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
1040 HValue* context, 1058 HValue* context,
1041 LoopBuilder::Direction direction) 1059 LoopBuilder::Direction direction)
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1154 CompilationPhase phase("H_Block building", info_); 1172 CompilationPhase phase("H_Block building", info_);
1155 set_current_block(graph()->entry_block()); 1173 set_current_block(graph()->entry_block());
1156 if (!BuildGraph()) return NULL; 1174 if (!BuildGraph()) return NULL;
1157 graph()->FinalizeUniqueness(); 1175 graph()->FinalizeUniqueness();
1158 return graph_; 1176 return graph_;
1159 } 1177 }
1160 1178
1161 1179
1162 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 1180 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
1163 ASSERT(current_block() != NULL); 1181 ASSERT(current_block() != NULL);
1164 ASSERT(!FLAG_emit_opt_code_positions || 1182 ASSERT(!FLAG_hydrogen_track_positions ||
1165 position_ != RelocInfo::kNoPosition || !info_->IsOptimizing()); 1183 !position_.IsUnknown() ||
1166 current_block()->AddInstruction(instr, position_); 1184 !info_->IsOptimizing());
1185 current_block()->AddInstruction(instr, source_position());
1167 if (graph()->IsInsideNoSideEffectsScope()) { 1186 if (graph()->IsInsideNoSideEffectsScope()) {
1168 instr->SetFlag(HValue::kHasNoObservableSideEffects); 1187 instr->SetFlag(HValue::kHasNoObservableSideEffects);
1169 } 1188 }
1170 return instr; 1189 return instr;
1171 } 1190 }
1172 1191
1173 1192
1174 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { 1193 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
1175 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || 1194 ASSERT(!FLAG_hydrogen_track_positions ||
1176 position_ != RelocInfo::kNoPosition); 1195 !info_->IsOptimizing() ||
1177 current_block()->Finish(last, position_); 1196 !position_.IsUnknown());
1197 current_block()->Finish(last, source_position());
1178 if (last->IsReturn() || last->IsAbnormalExit()) { 1198 if (last->IsReturn() || last->IsAbnormalExit()) {
1179 set_current_block(NULL); 1199 set_current_block(NULL);
1180 } 1200 }
1181 } 1201 }
1182 1202
1183 1203
1184 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { 1204 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
1185 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || 1205 ASSERT(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
1186 position_ != RelocInfo::kNoPosition); 1206 !position_.IsUnknown());
1187 current_block()->FinishExit(instruction, position_); 1207 current_block()->FinishExit(instruction, source_position());
1188 if (instruction->IsReturn() || instruction->IsAbnormalExit()) { 1208 if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1189 set_current_block(NULL); 1209 set_current_block(NULL);
1190 } 1210 }
1191 } 1211 }
1192 1212
1193 1213
1194 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { 1214 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
1195 if (FLAG_native_code_counters && counter->Enabled()) { 1215 if (FLAG_native_code_counters && counter->Enabled()) {
1196 HValue* reference = Add<HConstant>(ExternalReference(counter)); 1216 HValue* reference = Add<HConstant>(ExternalReference(counter));
1197 HValue* old_value = Add<HLoadNamedField>(reference, 1217 HValue* old_value = Add<HLoadNamedField>(
1198 HObjectAccess::ForCounter()); 1218 reference, static_cast<HValue*>(NULL), HObjectAccess::ForCounter());
1199 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1()); 1219 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
1200 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow 1220 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow
1201 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), 1221 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1202 new_value); 1222 new_value, STORE_TO_INITIALIZED_ENTRY);
1203 } 1223 }
1204 } 1224 }
1205 1225
1206 1226
1207 void HGraphBuilder::AddSimulate(BailoutId id, 1227 void HGraphBuilder::AddSimulate(BailoutId id,
1208 RemovableSimulate removable) { 1228 RemovableSimulate removable) {
1209 ASSERT(current_block() != NULL); 1229 ASSERT(current_block() != NULL);
1210 ASSERT(!graph()->IsInsideNoSideEffectsScope()); 1230 ASSERT(!graph()->IsInsideNoSideEffectsScope());
1211 current_block()->AddNewSimulate(id, removable); 1231 current_block()->AddNewSimulate(id, source_position(), removable);
1212 } 1232 }
1213 1233
1214 1234
1215 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 1235 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1216 HBasicBlock* b = graph()->CreateBasicBlock(); 1236 HBasicBlock* b = graph()->CreateBasicBlock();
1217 b->SetInitialEnvironment(env); 1237 b->SetInitialEnvironment(env);
1218 return b; 1238 return b;
1219 } 1239 }
1220 1240
1221 1241
1222 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 1242 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1223 HBasicBlock* header = graph()->CreateBasicBlock(); 1243 HBasicBlock* header = graph()->CreateBasicBlock();
1224 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 1244 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1225 header->SetInitialEnvironment(entry_env); 1245 header->SetInitialEnvironment(entry_env);
1226 header->AttachLoopInformation(); 1246 header->AttachLoopInformation();
1227 return header; 1247 return header;
1228 } 1248 }
1229 1249
1230 1250
1231 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { 1251 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
1232 if (obj->type().IsHeapObject()) return obj; 1252 if (obj->type().IsHeapObject()) return obj;
1233 return Add<HCheckHeapObject>(obj); 1253 return Add<HCheckHeapObject>(obj);
1234 } 1254 }
1235 1255
1236 1256
1237 void HGraphBuilder::FinishExitWithHardDeoptimization( 1257 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) {
1238 const char* reason, HBasicBlock* continuation) {
1239 PadEnvironmentForContinuation(current_block(), continuation);
1240 Add<HDeoptimize>(reason, Deoptimizer::EAGER); 1258 Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1241 if (graph()->IsInsideNoSideEffectsScope()) { 1259 FinishExitCurrentBlock(New<HAbnormalExit>());
1242 GotoNoSimulate(continuation);
1243 } else {
1244 Goto(continuation);
1245 }
1246 } 1260 }
1247 1261
1248 1262
1249 void HGraphBuilder::PadEnvironmentForContinuation(
1250 HBasicBlock* from,
1251 HBasicBlock* continuation) {
1252 if (continuation->last_environment() != NULL) {
1253 // When merging from a deopt block to a continuation, resolve differences in
1254 // environment by pushing constant 0 and popping extra values so that the
1255 // environments match during the join. Push 0 since it has the most specific
1256 // representation, and will not influence representation inference of the
1257 // phi.
1258 int continuation_env_length = continuation->last_environment()->length();
1259 while (continuation_env_length != from->last_environment()->length()) {
1260 if (continuation_env_length > from->last_environment()->length()) {
1261 from->last_environment()->Push(graph()->GetConstant0());
1262 } else {
1263 from->last_environment()->Pop();
1264 }
1265 }
1266 } else {
1267 ASSERT(continuation->predecessors()->length() == 0);
1268 }
1269 }
1270
1271
1272 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { 1263 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) {
1273 return Add<HCheckMaps>(obj, map, top_info()); 1264 return Add<HCheckMaps>(obj, map, top_info());
1274 } 1265 }
1275 1266
1276 1267
1277 HValue* HGraphBuilder::BuildCheckString(HValue* string) { 1268 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
1278 if (!string->type().IsString()) { 1269 if (!string->type().IsString()) {
1279 ASSERT(!string->IsConstant() || 1270 ASSERT(!string->IsConstant() ||
1280 !HConstant::cast(string)->HasStringValue()); 1271 !HConstant::cast(string)->HasStringValue());
1281 BuildCheckHeapObject(string); 1272 BuildCheckHeapObject(string);
1282 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); 1273 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1283 } 1274 }
1284 return string; 1275 return string;
1285 } 1276 }
1286 1277
1287 1278
1288 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { 1279 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1289 if (object->type().IsJSObject()) return object; 1280 if (object->type().IsJSObject()) return object;
1281 if (function->IsConstant() &&
1282 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
1283 Handle<JSFunction> f = Handle<JSFunction>::cast(
1284 HConstant::cast(function)->handle(isolate()));
1285 SharedFunctionInfo* shared = f->shared();
1286 if (!shared->is_classic_mode() || shared->native()) return object;
1287 }
1290 return Add<HWrapReceiver>(object, function); 1288 return Add<HWrapReceiver>(object, function);
1291 } 1289 }
1292 1290
1293 1291
1294 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1292 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
1295 HValue* elements, 1293 HValue* object,
1296 ElementsKind kind, 1294 HValue* elements,
1297 HValue* length, 1295 ElementsKind kind,
1298 HValue* key, 1296 HValue* length,
1299 bool is_js_array, 1297 HValue* key,
1300 bool is_store) { 1298 bool is_js_array,
1299 PropertyAccessType access_type) {
1301 IfBuilder length_checker(this); 1300 IfBuilder length_checker(this);
1302 1301
1303 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; 1302 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1304 length_checker.If<HCompareNumericAndBranch>(key, length, token); 1303 length_checker.If<HCompareNumericAndBranch>(key, length, token);
1305 1304
1306 length_checker.Then(); 1305 length_checker.Then();
1307 1306
1308 HValue* current_capacity = AddLoadFixedArrayLength(elements); 1307 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1309 1308
1310 IfBuilder capacity_checker(this); 1309 IfBuilder capacity_checker(this);
(...skipping 22 matching lines...) Expand all
1333 capacity_checker.End(); 1332 capacity_checker.End();
1334 1333
1335 if (is_js_array) { 1334 if (is_js_array) {
1336 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); 1335 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1337 new_length->ClearFlag(HValue::kCanOverflow); 1336 new_length->ClearFlag(HValue::kCanOverflow);
1338 1337
1339 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), 1338 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1340 new_length); 1339 new_length);
1341 } 1340 }
1342 1341
1343 if (is_store && kind == FAST_SMI_ELEMENTS) { 1342 if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
1344 HValue* checked_elements = environment()->Top(); 1343 HValue* checked_elements = environment()->Top();
1345 1344
1346 // Write zero to ensure that the new element is initialized with some smi. 1345 // Write zero to ensure that the new element is initialized with some smi.
1347 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind); 1346 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1348 } 1347 }
1349 1348
1350 length_checker.Else(); 1349 length_checker.Else();
1351 Add<HBoundsCheck>(key, length); 1350 Add<HBoundsCheck>(key, length);
1352 1351
1353 environment()->Push(elements); 1352 environment()->Push(elements);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 1404
1406 IfBuilder if_builder(this); 1405 IfBuilder if_builder(this);
1407 1406
1408 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); 1407 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1409 1408
1410 if_builder.Then(); 1409 if_builder.Then();
1411 1410
1412 HInstruction* elements_length = AddLoadFixedArrayLength(elements); 1411 HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1413 1412
1414 HInstruction* array_length = is_jsarray 1413 HInstruction* array_length = is_jsarray
1415 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind)) 1414 ? Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
1415 HObjectAccess::ForArrayLength(from_kind))
1416 : elements_length; 1416 : elements_length;
1417 1417
1418 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, 1418 BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1419 array_length, elements_length); 1419 array_length, elements_length);
1420 1420
1421 if_builder.End(); 1421 if_builder.End();
1422 } 1422 }
1423 1423
1424 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); 1424 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1425 } 1425 }
(...skipping 17 matching lines...) Expand all
1443 int32_t entry_size = SeededNumberDictionary::kEntrySize; 1443 int32_t entry_size = SeededNumberDictionary::kEntrySize;
1444 raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size)); 1444 raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size));
1445 raw_index->ClearFlag(HValue::kCanOverflow); 1445 raw_index->ClearFlag(HValue::kCanOverflow);
1446 1446
1447 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex; 1447 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex;
1448 HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset)); 1448 HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset));
1449 key_index->ClearFlag(HValue::kCanOverflow); 1449 key_index->ClearFlag(HValue::kCanOverflow);
1450 1450
1451 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index, 1451 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index,
1452 static_cast<HValue*>(NULL), 1452 static_cast<HValue*>(NULL),
1453 FAST_SMI_ELEMENTS); 1453 FAST_ELEMENTS);
1454 1454
1455 IfBuilder key_compare(this); 1455 IfBuilder key_compare(this);
1456 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key); 1456 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key);
1457 key_compare.Then(); 1457 key_compare.Then();
1458 { 1458 {
1459 // Key at the current probe doesn't match, try at the next probe. 1459 // Key at the current probe doesn't match, try at the next probe.
1460 HValue* result = BuildUncheckedDictionaryElementLoadHelper( 1460 HValue* result = BuildUncheckedDictionaryElementLoadHelper(
1461 elements, key, hash, mask, current_probe + 1); 1461 elements, key, hash, mask, current_probe + 1);
1462 if (result == NULL) { 1462 if (result == NULL) {
1463 key_compare.Deopt("probes exhausted in keyed load dictionary lookup"); 1463 key_compare.Deopt("probes exhausted in keyed load dictionary lookup");
1464 result = graph()->GetConstantUndefined(); 1464 result = graph()->GetConstantUndefined();
1465 } else { 1465 } else {
1466 Push(result); 1466 Push(result);
1467 } 1467 }
1468 } 1468 }
1469 key_compare.Else(); 1469 key_compare.Else();
1470 { 1470 {
1471 // Key at current probe matches. Details must be zero, otherwise the 1471 // Key at current probe matches. Details must be zero, otherwise the
1472 // dictionary element requires special handling. 1472 // dictionary element requires special handling.
1473 HValue* details_index = AddUncasted<HAdd>( 1473 HValue* details_index = AddUncasted<HAdd>(
1474 raw_index, Add<HConstant>(base_offset + 2)); 1474 raw_index, Add<HConstant>(base_offset + 2));
1475 details_index->ClearFlag(HValue::kCanOverflow); 1475 details_index->ClearFlag(HValue::kCanOverflow);
1476 1476
1477 HValue* details = Add<HLoadKeyed>(elements, details_index, 1477 HValue* details = Add<HLoadKeyed>(elements, details_index,
1478 static_cast<HValue*>(NULL), 1478 static_cast<HValue*>(NULL),
1479 FAST_SMI_ELEMENTS); 1479 FAST_ELEMENTS);
1480 IfBuilder details_compare(this); 1480 IfBuilder details_compare(this);
1481 details_compare.If<HCompareNumericAndBranch>(details, 1481 details_compare.If<HCompareNumericAndBranch>(details,
1482 graph()->GetConstant0(), 1482 graph()->GetConstant0(),
1483 Token::NE); 1483 Token::NE);
1484 details_compare.ThenDeopt("keyed load dictionary element not fast case"); 1484 details_compare.ThenDeopt("keyed load dictionary element not fast case");
1485 1485
1486 details_compare.Else(); 1486 details_compare.Else();
1487 { 1487 {
1488 // Key matches and details are zero --> fast case. Load and return the 1488 // Key matches and details are zero --> fast case. Load and return the
1489 // value. 1489 // value.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, 1539 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
1540 HValue* key) { 1540 HValue* key) {
1541 HValue* elements = AddLoadElements(receiver); 1541 HValue* elements = AddLoadElements(receiver);
1542 1542
1543 HValue* hash = BuildElementIndexHash(key); 1543 HValue* hash = BuildElementIndexHash(key);
1544 1544
1545 HValue* capacity = Add<HLoadKeyed>( 1545 HValue* capacity = Add<HLoadKeyed>(
1546 elements, 1546 elements,
1547 Add<HConstant>(NameDictionary::kCapacityIndex), 1547 Add<HConstant>(NameDictionary::kCapacityIndex),
1548 static_cast<HValue*>(NULL), 1548 static_cast<HValue*>(NULL),
1549 FAST_SMI_ELEMENTS); 1549 FAST_ELEMENTS);
1550 1550
1551 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); 1551 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
1552 mask->ChangeRepresentation(Representation::Integer32()); 1552 mask->ChangeRepresentation(Representation::Integer32());
1553 mask->ClearFlag(HValue::kCanOverflow); 1553 mask->ClearFlag(HValue::kCanOverflow);
1554 1554
1555 return BuildUncheckedDictionaryElementLoadHelper(elements, key, 1555 return BuildUncheckedDictionaryElementLoadHelper(elements, key,
1556 hash, mask, 0); 1556 hash, mask, 0);
1557 } 1557 }
1558 1558
1559 1559
1560 HValue* HGraphBuilder::BuildNumberToString(HValue* object, 1560 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
1561 Handle<Type> type) { 1561 HValue* index,
1562 HValue* input) {
1563 NoObservableSideEffectsScope scope(this);
1564
1565 // Compute the size of the RegExpResult followed by FixedArray with length.
1566 HValue* size = length;
1567 size = AddUncasted<HShl>(size, Add<HConstant>(kPointerSizeLog2));
1568 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>(
1569 JSRegExpResult::kSize + FixedArray::kHeaderSize)));
1570
1571 // Make sure size does not exceeds max regular heap object size.
1572 Add<HBoundsCheck>(size, Add<HConstant>(Page::kMaxRegularHeapObjectSize));
1573
1574 // Allocate the JSRegExpResult and the FixedArray in one step.
1575 HValue* result = Add<HAllocate>(
1576 size, HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE);
1577
1578 // Determine the elements FixedArray.
1579 HValue* elements = Add<HInnerAllocatedObject>(
1580 result, Add<HConstant>(JSRegExpResult::kSize));
1581
1582 // Initialize the JSRegExpResult header.
1583 HValue* global_object = Add<HLoadNamedField>(
1584 context(), static_cast<HValue*>(NULL),
1585 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
1586 HValue* native_context = Add<HLoadNamedField>(
1587 global_object, static_cast<HValue*>(NULL),
1588 HObjectAccess::ForGlobalObjectNativeContext());
1589 AddStoreMapNoWriteBarrier(result, Add<HLoadNamedField>(
1590 native_context, static_cast<HValue*>(NULL),
1591 HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
1592 Add<HStoreNamedField>(
1593 result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
1594 Add<HConstant>(isolate()->factory()->empty_fixed_array()));
1595 Add<HStoreNamedField>(
1596 result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1597 elements);
1598 Add<HStoreNamedField>(
1599 result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
1600
1601 // Initialize the additional fields.
1602 Add<HStoreNamedField>(
1603 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
1604 index);
1605 Add<HStoreNamedField>(
1606 result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
1607 input);
1608
1609 // Initialize the elements header.
1610 AddStoreMapConstantNoWriteBarrier(elements,
1611 isolate()->factory()->fixed_array_map());
1612 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), length);
1613
1614 // Initialize the elements contents with undefined.
1615 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
1616 index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
1617 {
1618 Add<HStoreKeyed>(elements, index, graph()->GetConstantUndefined(),
1619 FAST_ELEMENTS);
1620 }
1621 loop.EndBody();
1622
1623 return result;
1624 }
1625
1626
1627 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
1562 NoObservableSideEffectsScope scope(this); 1628 NoObservableSideEffectsScope scope(this);
1563 1629
1564 // Convert constant numbers at compile time. 1630 // Convert constant numbers at compile time.
1565 if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) { 1631 if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
1566 Handle<Object> number = HConstant::cast(object)->handle(isolate()); 1632 Handle<Object> number = HConstant::cast(object)->handle(isolate());
1567 Handle<String> result = isolate()->factory()->NumberToString(number); 1633 Handle<String> result = isolate()->factory()->NumberToString(number);
1568 return Add<HConstant>(result); 1634 return Add<HConstant>(result);
1569 } 1635 }
1570 1636
1571 // Create a joinable continuation. 1637 // Create a joinable continuation.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1607 } 1673 }
1608 if_objectiskey.JoinContinuation(&found); 1674 if_objectiskey.JoinContinuation(&found);
1609 } 1675 }
1610 if_objectissmi.Else(); 1676 if_objectissmi.Else();
1611 { 1677 {
1612 if (type->Is(Type::Smi())) { 1678 if (type->Is(Type::Smi())) {
1613 if_objectissmi.Deopt("Expected smi"); 1679 if_objectissmi.Deopt("Expected smi");
1614 } else { 1680 } else {
1615 // Check if the object is a heap number. 1681 // Check if the object is a heap number.
1616 IfBuilder if_objectisnumber(this); 1682 IfBuilder if_objectisnumber(this);
1617 if_objectisnumber.If<HCompareMap>( 1683 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
1618 object, isolate()->factory()->heap_number_map()); 1684 object, isolate()->factory()->heap_number_map());
1619 if_objectisnumber.Then(); 1685 if_objectisnumber.Then();
1620 { 1686 {
1621 // Compute hash for heap number similar to double_get_hash(). 1687 // Compute hash for heap number similar to double_get_hash().
1622 HValue* low = Add<HLoadNamedField>( 1688 HValue* low = Add<HLoadNamedField>(
1623 object, HObjectAccess::ForHeapNumberValueLowestBits()); 1689 object, objectisnumber,
1690 HObjectAccess::ForHeapNumberValueLowestBits());
1624 HValue* high = Add<HLoadNamedField>( 1691 HValue* high = Add<HLoadNamedField>(
1625 object, HObjectAccess::ForHeapNumberValueHighestBits()); 1692 object, objectisnumber,
1693 HObjectAccess::ForHeapNumberValueHighestBits());
1626 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high); 1694 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
1627 hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask); 1695 hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
1628 1696
1629 // Load the key. 1697 // Load the key.
1630 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1()); 1698 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1631 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, 1699 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1632 static_cast<HValue*>(NULL), 1700 static_cast<HValue*>(NULL),
1633 FAST_ELEMENTS, ALLOW_RETURN_HOLE); 1701 FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1634 1702
1635 // Check if key is a heap number (the number string cache contains only 1703 // Check if key is a heap number (the number string cache contains only
1636 // SMIs and heap number, so it is sufficient to do a SMI check here). 1704 // SMIs and heap number, so it is sufficient to do a SMI check here).
1637 IfBuilder if_keyisnotsmi(this); 1705 IfBuilder if_keyisnotsmi(this);
1638 if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key); 1706 HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1639 if_keyisnotsmi.Then(); 1707 if_keyisnotsmi.Then();
1640 { 1708 {
1641 // Check if values of key and object match. 1709 // Check if values of key and object match.
1642 IfBuilder if_keyeqobject(this); 1710 IfBuilder if_keyeqobject(this);
1643 if_keyeqobject.If<HCompareNumericAndBranch>( 1711 if_keyeqobject.If<HCompareNumericAndBranch>(
1644 Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()), 1712 Add<HLoadNamedField>(key, keyisnotsmi,
1645 Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()), 1713 HObjectAccess::ForHeapNumberValue()),
1714 Add<HLoadNamedField>(object, objectisnumber,
1715 HObjectAccess::ForHeapNumberValue()),
1646 Token::EQ); 1716 Token::EQ);
1647 if_keyeqobject.Then(); 1717 if_keyeqobject.Then();
1648 { 1718 {
1649 // Make the key_index available. 1719 // Make the key_index available.
1650 Push(key_index); 1720 Push(key_index);
1651 } 1721 }
1652 if_keyeqobject.JoinContinuation(&found); 1722 if_keyeqobject.JoinContinuation(&found);
1653 } 1723 }
1654 if_keyisnotsmi.JoinContinuation(&found); 1724 if_keyisnotsmi.JoinContinuation(&found);
1655 } 1725 }
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
2068 return Pop(); 2138 return Pop();
2069 } 2139 }
2070 2140
2071 2141
2072 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 2142 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
2073 HValue* checked_object, 2143 HValue* checked_object,
2074 HValue* key, 2144 HValue* key,
2075 HValue* val, 2145 HValue* val,
2076 bool is_js_array, 2146 bool is_js_array,
2077 ElementsKind elements_kind, 2147 ElementsKind elements_kind,
2078 bool is_store, 2148 PropertyAccessType access_type,
2079 LoadKeyedHoleMode load_mode, 2149 LoadKeyedHoleMode load_mode,
2080 KeyedAccessStoreMode store_mode) { 2150 KeyedAccessStoreMode store_mode) {
2081 ASSERT((!IsExternalArrayElementsKind(elements_kind) && 2151 ASSERT((!IsExternalArrayElementsKind(elements_kind) &&
2082 !IsFixedTypedArrayElementsKind(elements_kind)) || 2152 !IsFixedTypedArrayElementsKind(elements_kind)) ||
2083 !is_js_array); 2153 !is_js_array);
2084 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 2154 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
2085 // on a HElementsTransition instruction. The flag can also be removed if the 2155 // on a HElementsTransition instruction. The flag can also be removed if the
2086 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 2156 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
2087 // ElementsKind transitions. Finally, the dependency can be removed for stores 2157 // ElementsKind transitions. Finally, the dependency can be removed for stores
2088 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 2158 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
2089 // generated store code. 2159 // generated store code.
2090 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 2160 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
2091 (elements_kind == FAST_ELEMENTS && is_store)) { 2161 (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
2092 checked_object->ClearGVNFlag(kDependsOnElementsKind); 2162 checked_object->ClearDependsOnFlag(kElementsKind);
2093 } 2163 }
2094 2164
2095 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 2165 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
2096 bool fast_elements = IsFastObjectElementsKind(elements_kind); 2166 bool fast_elements = IsFastObjectElementsKind(elements_kind);
2097 HValue* elements = AddLoadElements(checked_object); 2167 HValue* elements = AddLoadElements(checked_object);
2098 if (is_store && (fast_elements || fast_smi_only_elements) && 2168 if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
2099 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 2169 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
2100 HCheckMaps* check_cow_map = Add<HCheckMaps>( 2170 HCheckMaps* check_cow_map = Add<HCheckMaps>(
2101 elements, isolate()->factory()->fixed_array_map(), top_info()); 2171 elements, isolate()->factory()->fixed_array_map(), top_info());
2102 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 2172 check_cow_map->ClearDependsOnFlag(kElementsKind);
2103 } 2173 }
2104 HInstruction* length = NULL; 2174 HInstruction* length = NULL;
2105 if (is_js_array) { 2175 if (is_js_array) {
2106 length = Add<HLoadNamedField>( 2176 length = Add<HLoadNamedField>(
2107 checked_object, HObjectAccess::ForArrayLength(elements_kind)); 2177 checked_object, static_cast<HValue*>(NULL),
2178 HObjectAccess::ForArrayLength(elements_kind));
2108 } else { 2179 } else {
2109 length = AddLoadFixedArrayLength(elements); 2180 length = AddLoadFixedArrayLength(elements);
2110 } 2181 }
2111 length->set_type(HType::Smi()); 2182 length->set_type(HType::Smi());
2112 HValue* checked_key = NULL; 2183 HValue* checked_key = NULL;
2113 if (IsExternalArrayElementsKind(elements_kind) || 2184 if (IsExternalArrayElementsKind(elements_kind) ||
2114 IsFixedTypedArrayElementsKind(elements_kind)) { 2185 IsFixedTypedArrayElementsKind(elements_kind)) {
2115 HValue* backing_store; 2186 HValue* backing_store;
2116 if (IsExternalArrayElementsKind(elements_kind)) { 2187 if (IsExternalArrayElementsKind(elements_kind)) {
2117 backing_store = 2188 backing_store = Add<HLoadNamedField>(
2118 Add<HLoadExternalArrayPointer>(elements); 2189 elements, static_cast<HValue*>(NULL),
2190 HObjectAccess::ForExternalArrayExternalPointer());
2119 } else { 2191 } else {
2120 backing_store = elements; 2192 backing_store = elements;
2121 } 2193 }
2122 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 2194 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2123 NoObservableSideEffectsScope no_effects(this); 2195 NoObservableSideEffectsScope no_effects(this);
2124 IfBuilder length_checker(this); 2196 IfBuilder length_checker(this);
2125 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 2197 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
2126 length_checker.Then(); 2198 length_checker.Then();
2127 IfBuilder negative_checker(this); 2199 IfBuilder negative_checker(this);
2128 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 2200 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
2129 key, graph()->GetConstant0(), Token::GTE); 2201 key, graph()->GetConstant0(), Token::GTE);
2130 negative_checker.Then(); 2202 negative_checker.Then();
2131 HInstruction* result = AddElementAccess( 2203 HInstruction* result = AddElementAccess(
2132 backing_store, key, val, bounds_check, elements_kind, is_store); 2204 backing_store, key, val, bounds_check, elements_kind, access_type);
2133 negative_checker.ElseDeopt("Negative key encountered"); 2205 negative_checker.ElseDeopt("Negative key encountered");
2134 negative_checker.End(); 2206 negative_checker.End();
2135 length_checker.End(); 2207 length_checker.End();
2136 return result; 2208 return result;
2137 } else { 2209 } else {
2138 ASSERT(store_mode == STANDARD_STORE); 2210 ASSERT(store_mode == STANDARD_STORE);
2139 checked_key = Add<HBoundsCheck>(key, length); 2211 checked_key = Add<HBoundsCheck>(key, length);
2140 return AddElementAccess( 2212 return AddElementAccess(
2141 backing_store, checked_key, val, 2213 backing_store, checked_key, val,
2142 checked_object, elements_kind, is_store); 2214 checked_object, elements_kind, access_type);
2143 } 2215 }
2144 } 2216 }
2145 ASSERT(fast_smi_only_elements || 2217 ASSERT(fast_smi_only_elements ||
2146 fast_elements || 2218 fast_elements ||
2147 IsFastDoubleElementsKind(elements_kind)); 2219 IsFastDoubleElementsKind(elements_kind));
2148 2220
2149 // In case val is stored into a fast smi array, assure that the value is a smi 2221 // In case val is stored into a fast smi array, assure that the value is a smi
2150 // before manipulating the backing store. Otherwise the actual store may 2222 // before manipulating the backing store. Otherwise the actual store may
2151 // deopt, leaving the backing store in an invalid state. 2223 // deopt, leaving the backing store in an invalid state.
2152 if (is_store && IsFastSmiElementsKind(elements_kind) && 2224 if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
2153 !val->type().IsSmi()) { 2225 !val->type().IsSmi()) {
2154 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); 2226 val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2155 } 2227 }
2156 2228
2157 if (IsGrowStoreMode(store_mode)) { 2229 if (IsGrowStoreMode(store_mode)) {
2158 NoObservableSideEffectsScope no_effects(this); 2230 NoObservableSideEffectsScope no_effects(this);
2159 elements = BuildCheckForCapacityGrow(checked_object, elements, 2231 elements = BuildCheckForCapacityGrow(checked_object, elements,
2160 elements_kind, length, key, 2232 elements_kind, length, key,
2161 is_js_array, is_store); 2233 is_js_array, access_type);
2162 checked_key = key; 2234 checked_key = key;
2163 } else { 2235 } else {
2164 checked_key = Add<HBoundsCheck>(key, length); 2236 checked_key = Add<HBoundsCheck>(key, length);
2165 2237
2166 if (is_store && (fast_elements || fast_smi_only_elements)) { 2238 if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
2167 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 2239 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2168 NoObservableSideEffectsScope no_effects(this); 2240 NoObservableSideEffectsScope no_effects(this);
2169 elements = BuildCopyElementsOnWrite(checked_object, elements, 2241 elements = BuildCopyElementsOnWrite(checked_object, elements,
2170 elements_kind, length); 2242 elements_kind, length);
2171 } else { 2243 } else {
2172 HCheckMaps* check_cow_map = Add<HCheckMaps>( 2244 HCheckMaps* check_cow_map = Add<HCheckMaps>(
2173 elements, isolate()->factory()->fixed_array_map(), top_info()); 2245 elements, isolate()->factory()->fixed_array_map(), top_info());
2174 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 2246 check_cow_map->ClearDependsOnFlag(kElementsKind);
2175 } 2247 }
2176 } 2248 }
2177 } 2249 }
2178 return AddElementAccess(elements, checked_key, val, checked_object, 2250 return AddElementAccess(elements, checked_key, val, checked_object,
2179 elements_kind, is_store, load_mode); 2251 elements_kind, access_type, load_mode);
2180 } 2252 }
2181 2253
2182 2254
2183 2255
2184 HValue* HGraphBuilder::BuildAllocateArrayFromLength( 2256 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2185 JSArrayBuilder* array_builder, 2257 JSArrayBuilder* array_builder,
2186 HValue* length_argument) { 2258 HValue* length_argument) {
2187 if (length_argument->IsConstant() && 2259 if (length_argument->IsConstant() &&
2188 HConstant::cast(length_argument)->HasSmiValue()) { 2260 HConstant::cast(length_argument)->HasSmiValue()) {
2189 int array_length = HConstant::cast(length_argument)->Integer32Value(); 2261 int array_length = HConstant::cast(length_argument)->Integer32Value();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2237 } 2309 }
2238 2310
2239 HConstant* elements_size_value = Add<HConstant>(elements_size); 2311 HConstant* elements_size_value = Add<HConstant>(elements_size);
2240 HValue* mul = AddUncasted<HMul>(capacity, elements_size_value); 2312 HValue* mul = AddUncasted<HMul>(capacity, elements_size_value);
2241 mul->ClearFlag(HValue::kCanOverflow); 2313 mul->ClearFlag(HValue::kCanOverflow);
2242 2314
2243 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); 2315 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
2244 HValue* total_size = AddUncasted<HAdd>(mul, header_size); 2316 HValue* total_size = AddUncasted<HAdd>(mul, header_size);
2245 total_size->ClearFlag(HValue::kCanOverflow); 2317 total_size->ClearFlag(HValue::kCanOverflow);
2246 2318
2247 return Add<HAllocate>(total_size, HType::JSArray(), 2319 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ?
2248 isolate()->heap()->GetPretenureMode(), instance_type); 2320 isolate()->heap()->GetPretenureMode() : NOT_TENURED;
2321
2322 return Add<HAllocate>(total_size, HType::JSArray(), pretenure_flag,
2323 instance_type);
2249 } 2324 }
2250 2325
2251 2326
2252 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, 2327 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
2253 ElementsKind kind, 2328 ElementsKind kind,
2254 HValue* capacity) { 2329 HValue* capacity) {
2255 Factory* factory = isolate()->factory(); 2330 Factory* factory = isolate()->factory();
2256 Handle<Map> map = IsFastDoubleElementsKind(kind) 2331 Handle<Map> map = IsFastDoubleElementsKind(kind)
2257 ? factory->fixed_double_array_map() 2332 ? factory->fixed_double_array_map()
2258 : factory->fixed_array_map(); 2333 : factory->fixed_array_map();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2308 return elements; 2383 return elements;
2309 } 2384 }
2310 2385
2311 2386
2312 HInstruction* HGraphBuilder::AddElementAccess( 2387 HInstruction* HGraphBuilder::AddElementAccess(
2313 HValue* elements, 2388 HValue* elements,
2314 HValue* checked_key, 2389 HValue* checked_key,
2315 HValue* val, 2390 HValue* val,
2316 HValue* dependency, 2391 HValue* dependency,
2317 ElementsKind elements_kind, 2392 ElementsKind elements_kind,
2318 bool is_store, 2393 PropertyAccessType access_type,
2319 LoadKeyedHoleMode load_mode) { 2394 LoadKeyedHoleMode load_mode) {
2320 if (is_store) { 2395 if (access_type == STORE) {
2321 ASSERT(val != NULL); 2396 ASSERT(val != NULL);
2322 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS || 2397 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
2323 elements_kind == UINT8_CLAMPED_ELEMENTS) { 2398 elements_kind == UINT8_CLAMPED_ELEMENTS) {
2324 val = Add<HClampToUint8>(val); 2399 val = Add<HClampToUint8>(val);
2325 } 2400 }
2326 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, 2401 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2327 elements_kind == FAST_SMI_ELEMENTS 2402 elements_kind == FAST_SMI_ELEMENTS
2328 ? STORE_TO_INITIALIZED_ENTRY 2403 ? STORE_TO_INITIALIZED_ENTRY
2329 : INITIALIZING_STORE); 2404 : INITIALIZING_STORE);
2330 } 2405 }
2331 2406
2332 ASSERT(!is_store); 2407 ASSERT(access_type == LOAD);
2333 ASSERT(val == NULL); 2408 ASSERT(val == NULL);
2334 HLoadKeyed* load = Add<HLoadKeyed>( 2409 HLoadKeyed* load = Add<HLoadKeyed>(
2335 elements, checked_key, dependency, elements_kind, load_mode); 2410 elements, checked_key, dependency, elements_kind, load_mode);
2336 if (FLAG_opt_safe_uint32_operations && 2411 if (FLAG_opt_safe_uint32_operations &&
2337 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS || 2412 (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
2338 elements_kind == UINT32_ELEMENTS)) { 2413 elements_kind == UINT32_ELEMENTS)) {
2339 graph()->RecordUint32Instruction(load); 2414 graph()->RecordUint32Instruction(load);
2340 } 2415 }
2341 return load; 2416 return load;
2342 } 2417 }
2343 2418
2344 2419
2345 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { 2420 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) {
2346 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer()); 2421 return Add<HLoadNamedField>(
2422 object, static_cast<HValue*>(NULL), HObjectAccess::ForElementsPointer());
2347 } 2423 }
2348 2424
2349 2425
2350 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { 2426 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) {
2351 return Add<HLoadNamedField>(object, 2427 return Add<HLoadNamedField>(
2352 HObjectAccess::ForFixedArrayLength()); 2428 object, static_cast<HValue*>(NULL), HObjectAccess::ForFixedArrayLength());
2353 } 2429 }
2354 2430
2355 2431
2356 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { 2432 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
2357 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity, 2433 HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
2358 graph_->GetConstant1()); 2434 graph_->GetConstant1());
2359 2435
2360 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity); 2436 HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
2361 new_capacity->ClearFlag(HValue::kCanOverflow); 2437 new_capacity->ClearFlag(HValue::kCanOverflow);
2362 2438
2363 HValue* min_growth = Add<HConstant>(16); 2439 HValue* min_growth = Add<HConstant>(16);
2364 2440
2365 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth); 2441 new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
2366 new_capacity->ClearFlag(HValue::kCanOverflow); 2442 new_capacity->ClearFlag(HValue::kCanOverflow);
2367 2443
2368 return new_capacity; 2444 return new_capacity;
2369 } 2445 }
2370 2446
2371 2447
2372 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { 2448 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
2373 Heap* heap = isolate()->heap();
2374 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize 2449 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize
2375 : kPointerSize; 2450 : kPointerSize;
2376 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; 2451 int max_size = Page::kMaxRegularHeapObjectSize / element_size;
2377 max_size -= JSArray::kSize / element_size; 2452 max_size -= JSArray::kSize / element_size;
2378 HConstant* max_size_constant = Add<HConstant>(max_size); 2453 HConstant* max_size_constant = Add<HConstant>(max_size);
2379 Add<HBoundsCheck>(length, max_size_constant); 2454 Add<HBoundsCheck>(length, max_size_constant);
2380 } 2455 }
2381 2456
2382 2457
2383 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, 2458 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
2384 HValue* elements, 2459 HValue* elements,
2385 ElementsKind kind, 2460 ElementsKind kind,
2386 ElementsKind new_kind, 2461 ElementsKind new_kind,
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2526 HValue* size_in_bytes = Add<HConstant>(size); 2601 HValue* size_in_bytes = Add<HConstant>(size);
2527 HInstruction* object = Add<HAllocate>(size_in_bytes, 2602 HInstruction* object = Add<HAllocate>(size_in_bytes,
2528 HType::JSObject(), 2603 HType::JSObject(),
2529 NOT_TENURED, 2604 NOT_TENURED,
2530 JS_OBJECT_TYPE); 2605 JS_OBJECT_TYPE);
2531 2606
2532 // Copy the JS array part. 2607 // Copy the JS array part.
2533 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 2608 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
2534 if ((i != JSArray::kElementsOffset) || (length == 0)) { 2609 if ((i != JSArray::kElementsOffset) || (length == 0)) {
2535 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); 2610 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i);
2536 Add<HStoreNamedField>(object, access, 2611 Add<HStoreNamedField>(
2537 Add<HLoadNamedField>(boilerplate, access)); 2612 object, access, Add<HLoadNamedField>(
2613 boilerplate, static_cast<HValue*>(NULL), access));
2538 } 2614 }
2539 } 2615 }
2540 2616
2541 // Create an allocation site info if requested. 2617 // Create an allocation site info if requested.
2542 if (mode == TRACK_ALLOCATION_SITE) { 2618 if (mode == TRACK_ALLOCATION_SITE) {
2543 BuildCreateAllocationMemento( 2619 BuildCreateAllocationMemento(
2544 object, Add<HConstant>(JSArray::kSize), allocation_site); 2620 object, Add<HConstant>(JSArray::kSize), allocation_site);
2545 } 2621 }
2546 2622
2547 if (length > 0) { 2623 if (length > 0) {
2548 HValue* boilerplate_elements = AddLoadElements(boilerplate); 2624 HValue* boilerplate_elements = AddLoadElements(boilerplate);
2549 HValue* object_elements; 2625 HValue* object_elements;
2550 if (IsFastDoubleElementsKind(kind)) { 2626 if (IsFastDoubleElementsKind(kind)) {
2551 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); 2627 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length));
2552 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), 2628 object_elements = Add<HAllocate>(elems_size, HType::JSArray(),
2553 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); 2629 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE);
2554 } else { 2630 } else {
2555 HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length)); 2631 HValue* elems_size = Add<HConstant>(FixedArray::SizeFor(length));
2556 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), 2632 object_elements = Add<HAllocate>(elems_size, HType::JSArray(),
2557 NOT_TENURED, FIXED_ARRAY_TYPE); 2633 NOT_TENURED, FIXED_ARRAY_TYPE);
2558 } 2634 }
2559 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), 2635 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
2560 object_elements); 2636 object_elements);
2561 2637
2562 // Copy the elements array header. 2638 // Copy the elements array header.
2563 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { 2639 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
2564 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); 2640 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
2565 Add<HStoreNamedField>(object_elements, access, 2641 Add<HStoreNamedField>(
2566 Add<HLoadNamedField>(boilerplate_elements, access)); 2642 object_elements, access, Add<HLoadNamedField>(
2643 boilerplate_elements, static_cast<HValue*>(NULL), access));
2567 } 2644 }
2568 2645
2569 // Copy the elements array contents. 2646 // Copy the elements array contents.
2570 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold 2647 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold
2571 // copying loops with constant length up to a given boundary and use this 2648 // copying loops with constant length up to a given boundary and use this
2572 // helper here instead. 2649 // helper here instead.
2573 for (int i = 0; i < length; i++) { 2650 for (int i = 0; i < length; i++) {
2574 HValue* key_constant = Add<HConstant>(i); 2651 HValue* key_constant = Add<HConstant>(i);
2575 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, 2652 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant,
2576 static_cast<HValue*>(NULL), kind); 2653 static_cast<HValue*>(NULL), kind);
2577 Add<HStoreKeyed>(object_elements, key_constant, value, kind); 2654 Add<HStoreKeyed>(object_elements, key_constant, value, kind);
2578 } 2655 }
2579 } 2656 }
2580 2657
2581 return object; 2658 return object;
2582 } 2659 }
2583 2660
2584 2661
2585 void HGraphBuilder::BuildCompareNil( 2662 void HGraphBuilder::BuildCompareNil(
2586 HValue* value, 2663 HValue* value,
2587 Handle<Type> type, 2664 Type* type,
2588 HIfContinuation* continuation) { 2665 HIfContinuation* continuation) {
2589 IfBuilder if_nil(this); 2666 IfBuilder if_nil(this);
2590 bool some_case_handled = false; 2667 bool some_case_handled = false;
2591 bool some_case_missing = false; 2668 bool some_case_missing = false;
2592 2669
2593 if (type->Maybe(Type::Null())) { 2670 if (type->Maybe(Type::Null())) {
2594 if (some_case_handled) if_nil.Or(); 2671 if (some_case_handled) if_nil.Or();
2595 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); 2672 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
2596 some_case_handled = true; 2673 some_case_handled = true;
2597 } else { 2674 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2642 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( 2719 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
2643 previous_object, previous_object_size); 2720 previous_object, previous_object_size);
2644 AddStoreMapConstant( 2721 AddStoreMapConstant(
2645 allocation_memento, isolate()->factory()->allocation_memento_map()); 2722 allocation_memento, isolate()->factory()->allocation_memento_map());
2646 Add<HStoreNamedField>( 2723 Add<HStoreNamedField>(
2647 allocation_memento, 2724 allocation_memento,
2648 HObjectAccess::ForAllocationMementoSite(), 2725 HObjectAccess::ForAllocationMementoSite(),
2649 allocation_site); 2726 allocation_site);
2650 if (FLAG_allocation_site_pretenuring) { 2727 if (FLAG_allocation_site_pretenuring) {
2651 HValue* memento_create_count = Add<HLoadNamedField>( 2728 HValue* memento_create_count = Add<HLoadNamedField>(
2652 allocation_site, HObjectAccess::ForAllocationSiteOffset( 2729 allocation_site, static_cast<HValue*>(NULL),
2730 HObjectAccess::ForAllocationSiteOffset(
2653 AllocationSite::kPretenureCreateCountOffset)); 2731 AllocationSite::kPretenureCreateCountOffset));
2654 memento_create_count = AddUncasted<HAdd>( 2732 memento_create_count = AddUncasted<HAdd>(
2655 memento_create_count, graph()->GetConstant1()); 2733 memento_create_count, graph()->GetConstant1());
2656 // This smi value is reset to zero after every gc, overflow isn't a problem 2734 // This smi value is reset to zero after every gc, overflow isn't a problem
2657 // since the counter is bounded by the new space size. 2735 // since the counter is bounded by the new space size.
2658 memento_create_count->ClearFlag(HValue::kCanOverflow); 2736 memento_create_count->ClearFlag(HValue::kCanOverflow);
2659 HStoreNamedField* store = Add<HStoreNamedField>( 2737 HStoreNamedField* store = Add<HStoreNamedField>(
2660 allocation_site, HObjectAccess::ForAllocationSiteOffset( 2738 allocation_site, HObjectAccess::ForAllocationSiteOffset(
2661 AllocationSite::kPretenureCreateCountOffset), memento_create_count); 2739 AllocationSite::kPretenureCreateCountOffset), memento_create_count);
2662 // No write barrier needed to store a smi. 2740 // No write barrier needed to store a smi.
2663 store->SkipWriteBarrier(); 2741 store->SkipWriteBarrier();
2664 } 2742 }
2665 } 2743 }
2666 2744
2667 2745
2668 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) { 2746 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
2669 // Get the global context, then the native context 2747 // Get the global context, then the native context
2670 HInstruction* context = 2748 HInstruction* context =
2671 Add<HLoadNamedField>(closure, HObjectAccess::ForFunctionContextPointer()); 2749 Add<HLoadNamedField>(closure, static_cast<HValue*>(NULL),
2672 HInstruction* global_object = Add<HLoadNamedField>(context, 2750 HObjectAccess::ForFunctionContextPointer());
2751 HInstruction* global_object = Add<HLoadNamedField>(
2752 context, static_cast<HValue*>(NULL),
2673 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 2753 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
2674 HObjectAccess access = HObjectAccess::ForJSObjectOffset( 2754 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
2675 GlobalObject::kNativeContextOffset); 2755 GlobalObject::kNativeContextOffset);
2676 return Add<HLoadNamedField>(global_object, access); 2756 return Add<HLoadNamedField>(
2757 global_object, static_cast<HValue*>(NULL), access);
2677 } 2758 }
2678 2759
2679 2760
2680 HInstruction* HGraphBuilder::BuildGetNativeContext() { 2761 HInstruction* HGraphBuilder::BuildGetNativeContext() {
2681 // Get the global context, then the native context 2762 // Get the global context, then the native context
2682 HInstruction* global_object = Add<HGlobalObject>(); 2763 HValue* global_object = Add<HLoadNamedField>(
2683 HObjectAccess access = HObjectAccess::ForJSObjectOffset( 2764 context(), static_cast<HValue*>(NULL),
2684 GlobalObject::kNativeContextOffset); 2765 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
2685 return Add<HLoadNamedField>(global_object, access); 2766 return Add<HLoadNamedField>(
2767 global_object, static_cast<HValue*>(NULL),
2768 HObjectAccess::ForObservableJSObjectOffset(
2769 GlobalObject::kNativeContextOffset));
2686 } 2770 }
2687 2771
2688 2772
2689 HInstruction* HGraphBuilder::BuildGetArrayFunction() { 2773 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
2690 HInstruction* native_context = BuildGetNativeContext(); 2774 HInstruction* native_context = BuildGetNativeContext();
2691 HInstruction* index = 2775 HInstruction* index =
2692 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); 2776 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
2693 return Add<HLoadKeyed>( 2777 return Add<HLoadKeyed>(
2694 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2778 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2695 } 2779 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2729 // A constant map is fine. 2813 // A constant map is fine.
2730 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_), 2814 Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
2731 builder()->isolate()); 2815 builder()->isolate());
2732 return builder()->Add<HConstant>(map); 2816 return builder()->Add<HConstant>(map);
2733 } 2817 }
2734 2818
2735 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) { 2819 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
2736 // No need for a context lookup if the kind_ matches the initial 2820 // No need for a context lookup if the kind_ matches the initial
2737 // map, because we can just load the map in that case. 2821 // map, because we can just load the map in that case.
2738 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2822 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2739 return builder()->AddLoadNamedField(constructor_function_, access); 2823 return builder()->Add<HLoadNamedField>(
2824 constructor_function_, static_cast<HValue*>(NULL), access);
2740 } 2825 }
2741 2826
2742 // TODO(mvstanton): we should always have a constructor function if we 2827 // TODO(mvstanton): we should always have a constructor function if we
2743 // are creating a stub. 2828 // are creating a stub.
2744 HInstruction* native_context = constructor_function_ != NULL 2829 HInstruction* native_context = constructor_function_ != NULL
2745 ? builder()->BuildGetNativeContext(constructor_function_) 2830 ? builder()->BuildGetNativeContext(constructor_function_)
2746 : builder()->BuildGetNativeContext(); 2831 : builder()->BuildGetNativeContext();
2747 2832
2748 HInstruction* index = builder()->Add<HConstant>( 2833 HInstruction* index = builder()->Add<HConstant>(
2749 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 2834 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
2750 2835
2751 HInstruction* map_array = builder()->Add<HLoadKeyed>( 2836 HInstruction* map_array = builder()->Add<HLoadKeyed>(
2752 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2837 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2753 2838
2754 HInstruction* kind_index = builder()->Add<HConstant>(kind_); 2839 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
2755 2840
2756 return builder()->Add<HLoadKeyed>( 2841 return builder()->Add<HLoadKeyed>(
2757 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 2842 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
2758 } 2843 }
2759 2844
2760 2845
2761 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { 2846 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
2762 // Find the map near the constructor function 2847 // Find the map near the constructor function
2763 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 2848 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
2764 return builder()->AddLoadNamedField(constructor_function_, access); 2849 return builder()->Add<HLoadNamedField>(
2850 constructor_function_, static_cast<HValue*>(NULL), access);
2765 } 2851 }
2766 2852
2767 2853
2768 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( 2854 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
2769 HValue* length_node) { 2855 HValue* length_node) {
2770 ASSERT(length_node != NULL); 2856 ASSERT(length_node != NULL);
2771 2857
2772 int base_size = JSArray::kSize; 2858 int base_size = JSArray::kSize;
2773 if (mode_ == TRACK_ALLOCATION_SITE) { 2859 if (mode_ == TRACK_ALLOCATION_SITE) {
2774 base_size += AllocationMemento::kSize; 2860 base_size += AllocationMemento::kSize;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2871 2957
2872 2958
2873 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, 2959 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
2874 Handle<Map> map) { 2960 Handle<Map> map) {
2875 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), 2961 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
2876 Add<HConstant>(map)); 2962 Add<HConstant>(map));
2877 } 2963 }
2878 2964
2879 2965
2880 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { 2966 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
2881 HGlobalObject* global_object = Add<HGlobalObject>(); 2967 HValue* global_object = Add<HLoadNamedField>(
2882 HObjectAccess access = HObjectAccess::ForJSObjectOffset( 2968 context(), static_cast<HValue*>(NULL),
2969 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
2970 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
2883 GlobalObject::kBuiltinsOffset); 2971 GlobalObject::kBuiltinsOffset);
2884 HValue* builtins = Add<HLoadNamedField>(global_object, access); 2972 HValue* builtins = Add<HLoadNamedField>(
2885 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( 2973 global_object, static_cast<HValue*>(NULL), access);
2886 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); 2974 HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
2887 return Add<HLoadNamedField>(builtins, function_access); 2975 JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
2976 return Add<HLoadNamedField>(
2977 builtins, static_cast<HValue*>(NULL), function_access);
2888 } 2978 }
2889 2979
2890 2980
2891 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) 2981 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
2892 : HGraphBuilder(info), 2982 : HGraphBuilder(info),
2893 function_state_(NULL), 2983 function_state_(NULL),
2894 initial_function_state_(this, info, NORMAL_RETURN), 2984 initial_function_state_(this, info, NORMAL_RETURN, 0),
2895 ast_context_(NULL), 2985 ast_context_(NULL),
2896 break_scope_(NULL), 2986 break_scope_(NULL),
2897 inlined_count_(0), 2987 inlined_count_(0),
2898 globals_(10, info->zone()), 2988 globals_(10, info->zone()),
2899 inline_bailout_(false), 2989 inline_bailout_(false),
2900 osr_(new(info->zone()) HOsrBuilder(this)) { 2990 osr_(new(info->zone()) HOsrBuilder(this)) {
2901 // This is not initialized in the initializer list because the 2991 // This is not initialized in the initializer list because the
2902 // constructor for the initial state relies on function_state_ == NULL 2992 // constructor for the initial state relies on function_state_ == NULL
2903 // to know it's the initial state. 2993 // to know it's the initial state.
2904 function_state_= &initial_function_state_; 2994 function_state_= &initial_function_state_;
2905 InitializeAstVisitor(info->isolate()); 2995 InitializeAstVisitor(info->zone());
2906 if (FLAG_emit_opt_code_positions) { 2996 if (FLAG_hydrogen_track_positions) {
2907 SetSourcePosition(info->shared_info()->start_position()); 2997 SetSourcePosition(info->shared_info()->start_position());
2908 } 2998 }
2909 } 2999 }
2910 3000
2911 3001
2912 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, 3002 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
2913 HBasicBlock* second, 3003 HBasicBlock* second,
2914 BailoutId join_id) { 3004 BailoutId join_id) {
2915 if (first == NULL) { 3005 if (first == NULL) {
2916 return second; 3006 return second;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2965 3055
2966 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( 3056 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
2967 IterationStatement* statement) { 3057 IterationStatement* statement) {
2968 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) 3058 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
2969 ? osr()->BuildOsrLoopEntry(statement) 3059 ? osr()->BuildOsrLoopEntry(statement)
2970 : BuildLoopEntry(); 3060 : BuildLoopEntry();
2971 return loop_entry; 3061 return loop_entry;
2972 } 3062 }
2973 3063
2974 3064
2975 void HBasicBlock::FinishExit(HControlInstruction* instruction, int position) { 3065 void HBasicBlock::FinishExit(HControlInstruction* instruction,
3066 HSourcePosition position) {
2976 Finish(instruction, position); 3067 Finish(instruction, position);
2977 ClearEnvironment(); 3068 ClearEnvironment();
2978 } 3069 }
2979 3070
2980 3071
2981 HGraph::HGraph(CompilationInfo* info) 3072 HGraph::HGraph(CompilationInfo* info)
2982 : isolate_(info->isolate()), 3073 : isolate_(info->isolate()),
2983 next_block_id_(0), 3074 next_block_id_(0),
2984 entry_block_(NULL), 3075 entry_block_(NULL),
2985 blocks_(8, info->zone()), 3076 blocks_(8, info->zone()),
2986 values_(16, info->zone()), 3077 values_(16, info->zone()),
2987 phi_list_(NULL), 3078 phi_list_(NULL),
2988 uint32_instructions_(NULL), 3079 uint32_instructions_(NULL),
2989 osr_(NULL), 3080 osr_(NULL),
2990 info_(info), 3081 info_(info),
2991 zone_(info->zone()), 3082 zone_(info->zone()),
2992 is_recursive_(false), 3083 is_recursive_(false),
2993 use_optimistic_licm_(false), 3084 use_optimistic_licm_(false),
2994 depends_on_empty_array_proto_elements_(false), 3085 depends_on_empty_array_proto_elements_(false),
2995 type_change_checksum_(0), 3086 type_change_checksum_(0),
2996 maximum_environment_size_(0), 3087 maximum_environment_size_(0),
2997 no_side_effects_scope_count_(0), 3088 no_side_effects_scope_count_(0),
2998 disallow_adding_new_values_(false) { 3089 disallow_adding_new_values_(false),
3090 next_inline_id_(0),
3091 inlined_functions_(5, info->zone()) {
2999 if (info->IsStub()) { 3092 if (info->IsStub()) {
3000 HydrogenCodeStub* stub = info->code_stub(); 3093 HydrogenCodeStub* stub = info->code_stub();
3001 CodeStubInterfaceDescriptor* descriptor = 3094 CodeStubInterfaceDescriptor* descriptor =
3002 stub->GetInterfaceDescriptor(isolate_); 3095 stub->GetInterfaceDescriptor(isolate_);
3003 start_environment_ = 3096 start_environment_ =
3004 new(zone_) HEnvironment(zone_, descriptor->environment_length()); 3097 new(zone_) HEnvironment(zone_, descriptor->environment_length());
3005 } else { 3098 } else {
3099 TraceInlinedFunction(info->shared_info(), HSourcePosition::Unknown());
3006 start_environment_ = 3100 start_environment_ =
3007 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 3101 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
3008 } 3102 }
3009 start_environment_->set_ast_id(BailoutId::FunctionEntry()); 3103 start_environment_->set_ast_id(BailoutId::FunctionEntry());
3010 entry_block_ = CreateBasicBlock(); 3104 entry_block_ = CreateBasicBlock();
3011 entry_block_->SetInitialEnvironment(start_environment_); 3105 entry_block_->SetInitialEnvironment(start_environment_);
3012 } 3106 }
3013 3107
3014 3108
3015 HBasicBlock* HGraph::CreateBasicBlock() { 3109 HBasicBlock* HGraph::CreateBasicBlock() {
3016 HBasicBlock* result = new(zone()) HBasicBlock(this); 3110 HBasicBlock* result = new(zone()) HBasicBlock(this);
3017 blocks_.Add(result, zone()); 3111 blocks_.Add(result, zone());
3018 return result; 3112 return result;
3019 } 3113 }
3020 3114
3021 3115
3022 void HGraph::FinalizeUniqueness() { 3116 void HGraph::FinalizeUniqueness() {
3023 DisallowHeapAllocation no_gc; 3117 DisallowHeapAllocation no_gc;
3024 ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate())); 3118 ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
3025 for (int i = 0; i < blocks()->length(); ++i) { 3119 for (int i = 0; i < blocks()->length(); ++i) {
3026 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { 3120 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
3027 it.Current()->FinalizeUniqueness(); 3121 it.Current()->FinalizeUniqueness();
3028 } 3122 }
3029 } 3123 }
3030 } 3124 }
3031 3125
3032 3126
3127 int HGraph::TraceInlinedFunction(
3128 Handle<SharedFunctionInfo> shared,
3129 HSourcePosition position) {
3130 if (!FLAG_hydrogen_track_positions) {
3131 return 0;
3132 }
3133
3134 int id = 0;
3135 for (; id < inlined_functions_.length(); id++) {
3136 if (inlined_functions_[id].shared().is_identical_to(shared)) {
3137 break;
3138 }
3139 }
3140
3141 if (id == inlined_functions_.length()) {
3142 inlined_functions_.Add(InlinedFunctionInfo(shared), zone());
3143
3144 if (!shared->script()->IsUndefined()) {
3145 Handle<Script> script(Script::cast(shared->script()));
3146 if (!script->source()->IsUndefined()) {
3147 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
3148 PrintF(tracing_scope.file(),
3149 "--- FUNCTION SOURCE (%s) id{%d,%d} ---\n",
3150 shared->DebugName()->ToCString().get(),
3151 info()->optimization_id(),
3152 id);
3153
3154 {
3155 ConsStringIteratorOp op;
3156 StringCharacterStream stream(String::cast(script->source()),
3157 &op,
3158 shared->start_position());
3159 // fun->end_position() points to the last character in the stream. We
3160 // need to compensate by adding one to calculate the length.
3161 int source_len =
3162 shared->end_position() - shared->start_position() + 1;
3163 for (int i = 0; i < source_len; i++) {
3164 if (stream.HasMore()) {
3165 PrintF(tracing_scope.file(), "%c", stream.GetNext());
3166 }
3167 }
3168 }
3169
3170 PrintF(tracing_scope.file(), "\n--- END ---\n");
3171 }
3172 }
3173 }
3174
3175 int inline_id = next_inline_id_++;
3176
3177 if (inline_id != 0) {
3178 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
3179 PrintF(tracing_scope.file(), "INLINE (%s) id{%d,%d} AS %d AT ",
3180 shared->DebugName()->ToCString().get(),
3181 info()->optimization_id(),
3182 id,
3183 inline_id);
3184 position.PrintTo(tracing_scope.file());
3185 PrintF(tracing_scope.file(), "\n");
3186 }
3187
3188 return inline_id;
3189 }
3190
3191
3192 int HGraph::SourcePositionToScriptPosition(HSourcePosition pos) {
3193 if (!FLAG_hydrogen_track_positions || pos.IsUnknown()) {
3194 return pos.raw();
3195 }
3196
3197 return inlined_functions_[pos.inlining_id()].start_position() +
3198 pos.position();
3199 }
3200
3201
3033 // Block ordering was implemented with two mutually recursive methods, 3202 // Block ordering was implemented with two mutually recursive methods,
3034 // HGraph::Postorder and HGraph::PostorderLoopBlocks. 3203 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
3035 // The recursion could lead to stack overflow so the algorithm has been 3204 // The recursion could lead to stack overflow so the algorithm has been
3036 // implemented iteratively. 3205 // implemented iteratively.
3037 // At a high level the algorithm looks like this: 3206 // At a high level the algorithm looks like this:
3038 // 3207 //
3039 // Postorder(block, loop_header) : { 3208 // Postorder(block, loop_header) : {
3040 // if (block has already been visited or is of another loop) return; 3209 // if (block has already been visited or is of another loop) return;
3041 // mark block as visited; 3210 // mark block as visited;
3042 // if (block is a loop header) { 3211 // if (block is a loop header) {
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
3401 phi_list_->Add(phi, zone()); 3570 phi_list_->Add(phi, zone());
3402 } 3571 }
3403 } 3572 }
3404 } 3573 }
3405 3574
3406 3575
3407 // Implementation of utility class to encapsulate the translation state for 3576 // Implementation of utility class to encapsulate the translation state for
3408 // a (possibly inlined) function. 3577 // a (possibly inlined) function.
3409 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, 3578 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
3410 CompilationInfo* info, 3579 CompilationInfo* info,
3411 InliningKind inlining_kind) 3580 InliningKind inlining_kind,
3581 int inlining_id)
3412 : owner_(owner), 3582 : owner_(owner),
3413 compilation_info_(info), 3583 compilation_info_(info),
3414 call_context_(NULL), 3584 call_context_(NULL),
3415 inlining_kind_(inlining_kind), 3585 inlining_kind_(inlining_kind),
3416 function_return_(NULL), 3586 function_return_(NULL),
3417 test_context_(NULL), 3587 test_context_(NULL),
3418 entry_(NULL), 3588 entry_(NULL),
3419 arguments_object_(NULL), 3589 arguments_object_(NULL),
3420 arguments_elements_(NULL), 3590 arguments_elements_(NULL),
3591 inlining_id_(inlining_id),
3592 outer_source_position_(HSourcePosition::Unknown()),
3421 outer_(owner->function_state()) { 3593 outer_(owner->function_state()) {
3422 if (outer_ != NULL) { 3594 if (outer_ != NULL) {
3423 // State for an inline function. 3595 // State for an inline function.
3424 if (owner->ast_context()->IsTest()) { 3596 if (owner->ast_context()->IsTest()) {
3425 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 3597 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
3426 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 3598 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
3427 if_true->MarkAsInlineReturnTarget(owner->current_block()); 3599 if_true->MarkAsInlineReturnTarget(owner->current_block());
3428 if_false->MarkAsInlineReturnTarget(owner->current_block()); 3600 if_false->MarkAsInlineReturnTarget(owner->current_block());
3429 TestContext* outer_test_context = TestContext::cast(owner->ast_context()); 3601 TestContext* outer_test_context = TestContext::cast(owner->ast_context());
3430 Expression* cond = outer_test_context->condition(); 3602 Expression* cond = outer_test_context->condition();
3431 // The AstContext constructor pushed on the context stack. This newed 3603 // The AstContext constructor pushed on the context stack. This newed
3432 // instance is the reason that AstContext can't be BASE_EMBEDDED. 3604 // instance is the reason that AstContext can't be BASE_EMBEDDED.
3433 test_context_ = new TestContext(owner, cond, if_true, if_false); 3605 test_context_ = new TestContext(owner, cond, if_true, if_false);
3434 } else { 3606 } else {
3435 function_return_ = owner->graph()->CreateBasicBlock(); 3607 function_return_ = owner->graph()->CreateBasicBlock();
3436 function_return()->MarkAsInlineReturnTarget(owner->current_block()); 3608 function_return()->MarkAsInlineReturnTarget(owner->current_block());
3437 } 3609 }
3438 // Set this after possibly allocating a new TestContext above. 3610 // Set this after possibly allocating a new TestContext above.
3439 call_context_ = owner->ast_context(); 3611 call_context_ = owner->ast_context();
3440 } 3612 }
3441 3613
3442 // Push on the state stack. 3614 // Push on the state stack.
3443 owner->set_function_state(this); 3615 owner->set_function_state(this);
3616
3617 if (FLAG_hydrogen_track_positions) {
3618 outer_source_position_ = owner->source_position();
3619 owner->EnterInlinedSource(
3620 info->shared_info()->start_position(),
3621 inlining_id);
3622 owner->SetSourcePosition(info->shared_info()->start_position());
3623 }
3444 } 3624 }
3445 3625
3446 3626
3447 FunctionState::~FunctionState() { 3627 FunctionState::~FunctionState() {
3448 delete test_context_; 3628 delete test_context_;
3449 owner_->set_function_state(outer_); 3629 owner_->set_function_state(outer_);
3630
3631 if (FLAG_hydrogen_track_positions) {
3632 owner_->set_source_position(outer_source_position_);
3633 owner_->EnterInlinedSource(
3634 outer_->compilation_info()->shared_info()->start_position(),
3635 outer_->inlining_id());
3636 }
3450 } 3637 }
3451 3638
3452 3639
3453 // Implementation of utility classes to represent an expression's context in 3640 // Implementation of utility classes to represent an expression's context in
3454 // the AST. 3641 // the AST.
3455 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind) 3642 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
3456 : owner_(owner), 3643 : owner_(owner),
3457 kind_(kind), 3644 kind_(kind),
3458 outer_(owner->ast_context()), 3645 outer_(owner->ast_context()),
3459 for_typeof_(false) { 3646 for_typeof_(false) {
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
3908 4095
3909 #ifdef DEBUG 4096 #ifdef DEBUG
3910 for (int i = 0; i < block->phis()->length(); i++) { 4097 for (int i = 0; i < block->phis()->length(); i++) {
3911 HPhi* phi = block->phis()->at(i); 4098 HPhi* phi = block->phis()->at(i);
3912 ASSERT(phi->ActualValue() == phi); 4099 ASSERT(phi->ActualValue() == phi);
3913 } 4100 }
3914 #endif 4101 #endif
3915 4102
3916 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { 4103 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
3917 HInstruction* instruction = it.Current(); 4104 HInstruction* instruction = it.Current();
3918 if (instruction->ActualValue() != instruction) { 4105 if (instruction->ActualValue() == instruction) continue;
4106 if (instruction->CheckFlag(HValue::kIsDead)) {
4107 // The instruction was marked as deleted but left in the graph
4108 // as a control flow dependency point for subsequent
4109 // instructions.
4110 instruction->DeleteAndReplaceWith(instruction->ActualValue());
4111 } else {
3919 ASSERT(instruction->IsInformativeDefinition()); 4112 ASSERT(instruction->IsInformativeDefinition());
3920 if (instruction->IsPurelyInformativeDefinition()) { 4113 if (instruction->IsPurelyInformativeDefinition()) {
3921 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); 4114 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
3922 } else { 4115 } else {
3923 instruction->ReplaceAllUsesWith(instruction->ActualValue()); 4116 instruction->ReplaceAllUsesWith(instruction->ActualValue());
3924 } 4117 }
3925 } 4118 }
3926 } 4119 }
3927 } 4120 }
3928 } 4121 }
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
4226 ZoneList<CaseClause*>* clauses = stmt->cases(); 4419 ZoneList<CaseClause*>* clauses = stmt->cases();
4227 int clause_count = clauses->length(); 4420 int clause_count = clauses->length();
4228 ZoneList<HBasicBlock*> body_blocks(clause_count, zone()); 4421 ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
4229 if (clause_count > kCaseClauseLimit) { 4422 if (clause_count > kCaseClauseLimit) {
4230 return Bailout(kSwitchStatementTooManyClauses); 4423 return Bailout(kSwitchStatementTooManyClauses);
4231 } 4424 }
4232 4425
4233 CHECK_ALIVE(VisitForValue(stmt->tag())); 4426 CHECK_ALIVE(VisitForValue(stmt->tag()));
4234 Add<HSimulate>(stmt->EntryId()); 4427 Add<HSimulate>(stmt->EntryId());
4235 HValue* tag_value = Top(); 4428 HValue* tag_value = Top();
4236 Handle<Type> tag_type = stmt->tag()->bounds().lower; 4429 Type* tag_type = stmt->tag()->bounds().lower;
4237 4430
4238 // 1. Build all the tests, with dangling true branches 4431 // 1. Build all the tests, with dangling true branches
4239 BailoutId default_id = BailoutId::None(); 4432 BailoutId default_id = BailoutId::None();
4240 for (int i = 0; i < clause_count; ++i) { 4433 for (int i = 0; i < clause_count; ++i) {
4241 CaseClause* clause = clauses->at(i); 4434 CaseClause* clause = clauses->at(i);
4242 if (clause->is_default()) { 4435 if (clause->is_default()) {
4243 body_blocks.Add(NULL, zone()); 4436 body_blocks.Add(NULL, zone());
4244 if (default_id.IsNone()) default_id = clause->EntryId(); 4437 if (default_id.IsNone()) default_id = clause->EntryId();
4245 continue; 4438 continue;
4246 } 4439 }
4247 4440
4248 // Generate a compare and branch. 4441 // Generate a compare and branch.
4249 CHECK_ALIVE(VisitForValue(clause->label())); 4442 CHECK_ALIVE(VisitForValue(clause->label()));
4250 HValue* label_value = Pop(); 4443 HValue* label_value = Pop();
4251 4444
4252 Handle<Type> label_type = clause->label()->bounds().lower; 4445 Type* label_type = clause->label()->bounds().lower;
4253 Handle<Type> combined_type = clause->compare_type(); 4446 Type* combined_type = clause->compare_type();
4254 HControlInstruction* compare = BuildCompareInstruction( 4447 HControlInstruction* compare = BuildCompareInstruction(
4255 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type, 4448 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
4256 combined_type, stmt->tag()->position(), clause->label()->position(), 4449 combined_type,
4257 clause->id()); 4450 ScriptPositionToSourcePosition(stmt->tag()->position()),
4451 ScriptPositionToSourcePosition(clause->label()->position()),
4452 PUSH_BEFORE_SIMULATE, clause->id());
4258 4453
4259 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 4454 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4260 HBasicBlock* body_block = graph()->CreateBasicBlock(); 4455 HBasicBlock* body_block = graph()->CreateBasicBlock();
4261 body_blocks.Add(body_block, zone()); 4456 body_blocks.Add(body_block, zone());
4262 compare->SetSuccessorAt(0, body_block); 4457 compare->SetSuccessorAt(0, body_block);
4263 compare->SetSuccessorAt(1, next_test_block); 4458 compare->SetSuccessorAt(1, next_test_block);
4264 FinishCurrentBlock(compare); 4459 FinishCurrentBlock(compare);
4265 4460
4266 set_current_block(body_block); 4461 set_current_block(body_block);
4267 Drop(1); // tag_value 4462 Drop(1); // tag_value
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
4667 set_current_block(join); 4862 set_current_block(join);
4668 if (join != NULL && !ast_context()->IsEffect()) { 4863 if (join != NULL && !ast_context()->IsEffect()) {
4669 return ast_context()->ReturnValue(Pop()); 4864 return ast_context()->ReturnValue(Pop());
4670 } 4865 }
4671 } 4866 }
4672 } 4867 }
4673 4868
4674 4869
4675 HOptimizedGraphBuilder::GlobalPropertyAccess 4870 HOptimizedGraphBuilder::GlobalPropertyAccess
4676 HOptimizedGraphBuilder::LookupGlobalProperty( 4871 HOptimizedGraphBuilder::LookupGlobalProperty(
4677 Variable* var, LookupResult* lookup, bool is_store) { 4872 Variable* var, LookupResult* lookup, PropertyAccessType access_type) {
4678 if (var->is_this() || !current_info()->has_global_object()) { 4873 if (var->is_this() || !current_info()->has_global_object()) {
4679 return kUseGeneric; 4874 return kUseGeneric;
4680 } 4875 }
4681 Handle<GlobalObject> global(current_info()->global_object()); 4876 Handle<GlobalObject> global(current_info()->global_object());
4682 global->Lookup(*var->name(), lookup); 4877 global->Lookup(*var->name(), lookup);
4683 if (!lookup->IsNormal() || 4878 if (!lookup->IsNormal() ||
4684 (is_store && lookup->IsReadOnly()) || 4879 (access_type == STORE && lookup->IsReadOnly()) ||
4685 lookup->holder() != *global) { 4880 lookup->holder() != *global) {
4686 return kUseGeneric; 4881 return kUseGeneric;
4687 } 4882 }
4688 4883
4689 return kUseCell; 4884 return kUseCell;
4690 } 4885 }
4691 4886
4692 4887
4693 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { 4888 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
4694 ASSERT(var->IsContextSlot()); 4889 ASSERT(var->IsContextSlot());
4695 HValue* context = environment()->context(); 4890 HValue* context = environment()->context();
4696 int length = current_info()->scope()->ContextChainLength(var->scope()); 4891 int length = current_info()->scope()->ContextChainLength(var->scope());
4697 while (length-- > 0) { 4892 while (length-- > 0) {
4698 context = Add<HOuterContext>(context); 4893 context = Add<HLoadNamedField>(
4894 context, static_cast<HValue*>(NULL),
4895 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4699 } 4896 }
4700 return context; 4897 return context;
4701 } 4898 }
4702 4899
4703 4900
4704 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 4901 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
4705 if (expr->is_this()) { 4902 if (expr->is_this()) {
4706 current_info()->set_this_has_uses(true); 4903 current_info()->set_this_has_uses(true);
4707 } 4904 }
4708 4905
(...skipping 10 matching lines...) Expand all
4719 // Handle known global constants like 'undefined' specially to avoid a 4916 // Handle known global constants like 'undefined' specially to avoid a
4720 // load from a global cell for them. 4917 // load from a global cell for them.
4721 Handle<Object> constant_value = 4918 Handle<Object> constant_value =
4722 isolate()->factory()->GlobalConstantFor(variable->name()); 4919 isolate()->factory()->GlobalConstantFor(variable->name());
4723 if (!constant_value.is_null()) { 4920 if (!constant_value.is_null()) {
4724 HConstant* instr = New<HConstant>(constant_value); 4921 HConstant* instr = New<HConstant>(constant_value);
4725 return ast_context()->ReturnInstruction(instr, expr->id()); 4922 return ast_context()->ReturnInstruction(instr, expr->id());
4726 } 4923 }
4727 4924
4728 LookupResult lookup(isolate()); 4925 LookupResult lookup(isolate());
4729 GlobalPropertyAccess type = 4926 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, LOAD);
4730 LookupGlobalProperty(variable, &lookup, false);
4731 4927
4732 if (type == kUseCell && 4928 if (type == kUseCell &&
4733 current_info()->global_object()->IsAccessCheckNeeded()) { 4929 current_info()->global_object()->IsAccessCheckNeeded()) {
4734 type = kUseGeneric; 4930 type = kUseGeneric;
4735 } 4931 }
4736 4932
4737 if (type == kUseCell) { 4933 if (type == kUseCell) {
4738 Handle<GlobalObject> global(current_info()->global_object()); 4934 Handle<GlobalObject> global(current_info()->global_object());
4739 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 4935 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
4740 if (cell->type()->IsConstant()) { 4936 if (cell->type()->IsConstant()) {
4741 cell->AddDependentCompilationInfo(top_info()); 4937 cell->AddDependentCompilationInfo(top_info());
4742 Handle<Object> constant_object = cell->type()->AsConstant(); 4938 Handle<Object> constant_object = cell->type()->AsConstant();
4743 if (constant_object->IsConsString()) { 4939 if (constant_object->IsConsString()) {
4744 constant_object = 4940 constant_object =
4745 FlattenGetString(Handle<String>::cast(constant_object)); 4941 FlattenGetString(Handle<String>::cast(constant_object));
4746 } 4942 }
4747 HConstant* constant = New<HConstant>(constant_object); 4943 HConstant* constant = New<HConstant>(constant_object);
4748 return ast_context()->ReturnInstruction(constant, expr->id()); 4944 return ast_context()->ReturnInstruction(constant, expr->id());
4749 } else { 4945 } else {
4750 HLoadGlobalCell* instr = 4946 HLoadGlobalCell* instr =
4751 New<HLoadGlobalCell>(cell, lookup.GetPropertyDetails()); 4947 New<HLoadGlobalCell>(cell, lookup.GetPropertyDetails());
4752 return ast_context()->ReturnInstruction(instr, expr->id()); 4948 return ast_context()->ReturnInstruction(instr, expr->id());
4753 } 4949 }
4754 } else { 4950 } else {
4755 HGlobalObject* global_object = Add<HGlobalObject>(); 4951 HValue* global_object = Add<HLoadNamedField>(
4952 context(), static_cast<HValue*>(NULL),
4953 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
4756 HLoadGlobalGeneric* instr = 4954 HLoadGlobalGeneric* instr =
4757 New<HLoadGlobalGeneric>(global_object, 4955 New<HLoadGlobalGeneric>(global_object,
4758 variable->name(), 4956 variable->name(),
4759 ast_context()->is_for_typeof()); 4957 ast_context()->is_for_typeof());
4760 return ast_context()->ReturnInstruction(instr, expr->id()); 4958 return ast_context()->ReturnInstruction(instr, expr->id());
4761 } 4959 }
4762 } 4960 }
4763 4961
4764 case Variable::PARAMETER: 4962 case Variable::PARAMETER:
4765 case Variable::LOCAL: { 4963 case Variable::LOCAL: {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
4800 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 4998 Handle<JSFunction> closure = function_state()->compilation_info()->closure();
4801 Handle<FixedArray> literals(closure->literals()); 4999 Handle<FixedArray> literals(closure->literals());
4802 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, 5000 HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
4803 expr->pattern(), 5001 expr->pattern(),
4804 expr->flags(), 5002 expr->flags(),
4805 expr->literal_index()); 5003 expr->literal_index());
4806 return ast_context()->ReturnInstruction(instr, expr->id()); 5004 return ast_context()->ReturnInstruction(instr, expr->id());
4807 } 5005 }
4808 5006
4809 5007
4810 static bool CanInlinePropertyAccess(Map* type) { 5008 static bool CanInlinePropertyAccess(Type* type) {
4811 return type->IsJSObjectMap() && 5009 if (type->Is(Type::NumberOrString())) return true;
4812 !type->is_dictionary_map() && 5010 if (!type->IsClass()) return false;
4813 !type->has_named_interceptor(); 5011 Handle<Map> map = type->AsClass();
5012 return map->IsJSObjectMap() &&
5013 !map->is_dictionary_map() &&
5014 !map->has_named_interceptor();
4814 } 5015 }
4815 5016
4816 5017
4817 static void LookupInPrototypes(Handle<Map> map,
4818 Handle<String> name,
4819 LookupResult* lookup) {
4820 while (map->prototype()->IsJSObject()) {
4821 Handle<JSObject> holder(JSObject::cast(map->prototype()));
4822 map = Handle<Map>(holder->map());
4823 if (!CanInlinePropertyAccess(*map)) break;
4824 map->LookupDescriptor(*holder, *name, lookup);
4825 if (lookup->IsFound()) return;
4826 }
4827 lookup->NotFound();
4828 }
4829
4830
4831 // Tries to find a JavaScript accessor of the given name in the prototype chain
4832 // starting at the given map. Return true iff there is one, including the
4833 // corresponding AccessorPair plus its holder (which could be null when the
4834 // accessor is found directly in the given map).
4835 static bool LookupAccessorPair(Handle<Map> map,
4836 Handle<String> name,
4837 Handle<AccessorPair>* accessors,
4838 Handle<JSObject>* holder) {
4839 Isolate* isolate = map->GetIsolate();
4840 LookupResult lookup(isolate);
4841
4842 // Check for a JavaScript accessor directly in the map.
4843 map->LookupDescriptor(NULL, *name, &lookup);
4844 if (lookup.IsPropertyCallbacks()) {
4845 Handle<Object> callback(lookup.GetValueFromMap(*map), isolate);
4846 if (!callback->IsAccessorPair()) return false;
4847 *accessors = Handle<AccessorPair>::cast(callback);
4848 *holder = Handle<JSObject>();
4849 return true;
4850 }
4851
4852 // Everything else, e.g. a field, can't be an accessor call.
4853 if (lookup.IsFound()) return false;
4854
4855 // Check for a JavaScript accessor somewhere in the proto chain.
4856 LookupInPrototypes(map, name, &lookup);
4857 if (lookup.IsPropertyCallbacks()) {
4858 Handle<Object> callback(lookup.GetValue(), isolate);
4859 if (!callback->IsAccessorPair()) return false;
4860 *accessors = Handle<AccessorPair>::cast(callback);
4861 *holder = Handle<JSObject>(lookup.holder());
4862 return true;
4863 }
4864
4865 // We haven't found a JavaScript accessor anywhere.
4866 return false;
4867 }
4868
4869
4870 static bool LookupSetter(Handle<Map> map,
4871 Handle<String> name,
4872 Handle<JSFunction>* setter,
4873 Handle<JSObject>* holder) {
4874 Handle<AccessorPair> accessors;
4875 if (LookupAccessorPair(map, name, &accessors, holder) &&
4876 accessors->setter()->IsJSFunction()) {
4877 Handle<JSFunction> func(JSFunction::cast(accessors->setter()));
4878 CallOptimization call_optimization(func);
4879 // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
4880 if (call_optimization.is_simple_api_call()) return false;
4881 *setter = func;
4882 return true;
4883 }
4884 return false;
4885 }
4886
4887
4888 // Determines whether the given array or object literal boilerplate satisfies 5018 // Determines whether the given array or object literal boilerplate satisfies
4889 // all limits to be considered for fast deep-copying and computes the total 5019 // all limits to be considered for fast deep-copying and computes the total
4890 // size of all objects that are part of the graph. 5020 // size of all objects that are part of the graph.
4891 static bool IsFastLiteral(Handle<JSObject> boilerplate, 5021 static bool IsFastLiteral(Handle<JSObject> boilerplate,
4892 int max_depth, 5022 int max_depth,
4893 int* max_properties) { 5023 int* max_properties) {
4894 if (boilerplate->map()->is_deprecated()) { 5024 if (boilerplate->map()->is_deprecated()) {
4895 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); 5025 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
4896 if (result.is_null()) return false; 5026 if (result.is_null()) return false;
4897 } 5027 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
5021 case ObjectLiteral::Property::COMPUTED: 5151 case ObjectLiteral::Property::COMPUTED:
5022 if (key->value()->IsInternalizedString()) { 5152 if (key->value()->IsInternalizedString()) {
5023 if (property->emit_store()) { 5153 if (property->emit_store()) {
5024 CHECK_ALIVE(VisitForValue(value)); 5154 CHECK_ALIVE(VisitForValue(value));
5025 HValue* value = Pop(); 5155 HValue* value = Pop();
5026 Handle<Map> map = property->GetReceiverType(); 5156 Handle<Map> map = property->GetReceiverType();
5027 Handle<String> name = property->key()->AsPropertyName(); 5157 Handle<String> name = property->key()->AsPropertyName();
5028 HInstruction* store; 5158 HInstruction* store;
5029 if (map.is_null()) { 5159 if (map.is_null()) {
5030 // If we don't know the monomorphic type, do a generic store. 5160 // If we don't know the monomorphic type, do a generic store.
5031 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); 5161 CHECK_ALIVE(store = BuildNamedGeneric(
5162 STORE, literal, name, value));
5032 } else { 5163 } else {
5033 #if DEBUG 5164 PropertyAccessInfo info(this, STORE, ToType(map), name);
5034 Handle<JSFunction> setter; 5165 if (info.CanAccessMonomorphic()) {
5035 Handle<JSObject> holder; 5166 HValue* checked_literal = BuildCheckMap(literal, map);
5036 ASSERT(!LookupSetter(map, name, &setter, &holder)); 5167 ASSERT(!info.lookup()->IsPropertyCallbacks());
5037 #endif 5168 store = BuildMonomorphicAccess(
5038 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal, 5169 &info, literal, checked_literal, value,
5039 name, 5170 BailoutId::None(), BailoutId::None());
5040 value, 5171 } else {
5041 map)); 5172 CHECK_ALIVE(store = BuildNamedGeneric(
5173 STORE, literal, name, value));
5174 }
5042 } 5175 }
5043 AddInstruction(store); 5176 AddInstruction(store);
5044 if (store->HasObservableSideEffects()) { 5177 if (store->HasObservableSideEffects()) {
5045 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); 5178 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5046 } 5179 }
5047 } else { 5180 } else {
5048 CHECK_ALIVE(VisitForEffect(value)); 5181 CHECK_ALIVE(VisitForEffect(value));
5049 } 5182 }
5050 break; 5183 break;
5051 } 5184 }
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
5206 } 5339 }
5207 5340
5208 5341
5209 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, 5342 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
5210 Handle<Map> map) { 5343 Handle<Map> map) {
5211 BuildCheckHeapObject(object); 5344 BuildCheckHeapObject(object);
5212 return Add<HCheckMaps>(object, map, top_info()); 5345 return Add<HCheckMaps>(object, map, top_info());
5213 } 5346 }
5214 5347
5215 5348
5349 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
5350 PropertyAccessInfo* info,
5351 HValue* checked_object) {
5352 HObjectAccess access = info->access();
5353 if (access.representation().IsDouble()) {
5354 // Load the heap number.
5355 checked_object = Add<HLoadNamedField>(
5356 checked_object, static_cast<HValue*>(NULL),
5357 access.WithRepresentation(Representation::Tagged()));
5358 checked_object->set_type(HType::HeapNumber());
5359 // Load the double value from it.
5360 access = HObjectAccess::ForHeapNumberValue();
5361 }
5362 return New<HLoadNamedField>(
5363 checked_object, static_cast<HValue*>(NULL), access);
5364 }
5365
5366
5216 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( 5367 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
5368 PropertyAccessInfo* info,
5217 HValue* checked_object, 5369 HValue* checked_object,
5218 Handle<String> name, 5370 HValue* value) {
5219 HValue* value, 5371 bool transition_to_field = info->lookup()->IsTransition();
5220 Handle<Map> map, 5372 // TODO(verwaest): Move this logic into PropertyAccessInfo.
5221 LookupResult* lookup) { 5373 HObjectAccess field_access = HObjectAccess::ForField(
5222 ASSERT(lookup->IsFound()); 5374 info->map(), info->lookup(), info->name());
5223 // If the property does not exist yet, we have to check that it wasn't made
5224 // readonly or turned into a setter by some meanwhile modifications on the
5225 // prototype chain.
5226 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) {
5227 Object* proto = map->prototype();
5228 // First check that the prototype chain isn't affected already.
5229 LookupResult proto_result(isolate());
5230 proto->Lookup(*name, &proto_result);
5231 if (proto_result.IsProperty()) {
5232 // If the inherited property could induce readonly-ness, bail out.
5233 if (proto_result.IsReadOnly() || !proto_result.IsCacheable()) {
5234 Bailout(kImproperObjectOnPrototypeChainForStore);
5235 return NULL;
5236 }
5237 // We only need to check up to the preexisting property.
5238 proto = proto_result.holder();
5239 } else {
5240 // Otherwise, find the top prototype.
5241 while (proto->GetPrototype(isolate())->IsJSObject()) {
5242 proto = proto->GetPrototype(isolate());
5243 }
5244 ASSERT(proto->GetPrototype(isolate())->IsNull());
5245 }
5246 ASSERT(proto->IsJSObject());
5247 BuildCheckPrototypeMaps(
5248 Handle<JSObject>(JSObject::cast(map->prototype())),
5249 Handle<JSObject>(JSObject::cast(proto)));
5250 }
5251
5252 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
5253 bool transition_to_field = lookup->IsTransitionToField(*map);
5254 5375
5255 HStoreNamedField *instr; 5376 HStoreNamedField *instr;
5256 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { 5377 if (field_access.representation().IsDouble()) {
5257 HObjectAccess heap_number_access = 5378 HObjectAccess heap_number_access =
5258 field_access.WithRepresentation(Representation::Tagged()); 5379 field_access.WithRepresentation(Representation::Tagged());
5259 if (transition_to_field) { 5380 if (transition_to_field) {
5260 // The store requires a mutable HeapNumber to be allocated. 5381 // The store requires a mutable HeapNumber to be allocated.
5261 NoObservableSideEffectsScope no_side_effects(this); 5382 NoObservableSideEffectsScope no_side_effects(this);
5262 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); 5383 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
5384
5385 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ?
5386 isolate()->heap()->GetPretenureMode() : NOT_TENURED;
5387
5263 HInstruction* heap_number = Add<HAllocate>(heap_number_size, 5388 HInstruction* heap_number = Add<HAllocate>(heap_number_size,
5264 HType::HeapNumber(), isolate()->heap()->GetPretenureMode(), 5389 HType::HeapNumber(),
5390 pretenure_flag,
5265 HEAP_NUMBER_TYPE); 5391 HEAP_NUMBER_TYPE);
5266 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); 5392 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map());
5267 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), 5393 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
5268 value); 5394 value);
5269 instr = New<HStoreNamedField>(checked_object->ActualValue(), 5395 instr = New<HStoreNamedField>(checked_object->ActualValue(),
5270 heap_number_access, 5396 heap_number_access,
5271 heap_number); 5397 heap_number);
5272 } else { 5398 } else {
5273 // Already holds a HeapNumber; load the box and write its value field. 5399 // Already holds a HeapNumber; load the box and write its value field.
5274 HInstruction* heap_number = Add<HLoadNamedField>(checked_object, 5400 HInstruction* heap_number = Add<HLoadNamedField>(
5275 heap_number_access); 5401 checked_object, static_cast<HValue*>(NULL), heap_number_access);
5276 heap_number->set_type(HType::HeapNumber()); 5402 heap_number->set_type(HType::HeapNumber());
5277 instr = New<HStoreNamedField>(heap_number, 5403 instr = New<HStoreNamedField>(heap_number,
5278 HObjectAccess::ForHeapNumberValue(), 5404 HObjectAccess::ForHeapNumberValue(),
5279 value); 5405 value, STORE_TO_INITIALIZED_ENTRY);
5280 } 5406 }
5281 } else { 5407 } else {
5282 // This is a normal store. 5408 // This is a normal store.
5283 instr = New<HStoreNamedField>( 5409 instr = New<HStoreNamedField>(
5284 checked_object->ActualValue(), field_access, value, 5410 checked_object->ActualValue(), field_access, value,
5285 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); 5411 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
5286 } 5412 }
5287 5413
5288 if (transition_to_field) { 5414 if (transition_to_field) {
5289 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); 5415 HConstant* transition_constant = Add<HConstant>(info->transition());
5290 HConstant* transition_constant = Add<HConstant>(transition);
5291 instr->SetTransition(transition_constant, top_info()); 5416 instr->SetTransition(transition_constant, top_info());
5292 // TODO(fschneider): Record the new map type of the object in the IR to 5417 instr->SetChangesFlag(kMaps);
5293 // enable elimination of redundant checks after the transition store.
5294 instr->SetGVNFlag(kChangesMaps);
5295 } 5418 }
5296 return instr; 5419 return instr;
5297 } 5420 }
5298 5421
5299 5422
5300 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( 5423 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
5301 HValue* object, 5424 PropertyAccessInfo* info) {
5302 Handle<String> name, 5425 if (!CanInlinePropertyAccess(type_)) return false;
5303 HValue* value) {
5304 return New<HStoreNamedGeneric>(
5305 object,
5306 name,
5307 value,
5308 function_strict_mode_flag());
5309 }
5310 5426
5427 // Currently only handle Type::Number as a polymorphic case.
5428 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5429 // instruction.
5430 if (type_->Is(Type::Number())) return false;
5311 5431
5312 // Sets the lookup result and returns true if the load/store can be inlined. 5432 // Values are only compatible for monomorphic load if they all behave the same
5313 static bool ComputeStoreField(Handle<Map> type, 5433 // regarding value wrappers.
5314 Handle<String> name, 5434 if (type_->Is(Type::NumberOrString())) {
5315 LookupResult* lookup, 5435 if (!info->type_->Is(Type::NumberOrString())) return false;
5316 bool lookup_transition = true) { 5436 } else {
5317 ASSERT(!type->is_observed()); 5437 if (info->type_->Is(Type::NumberOrString())) return false;
5318 if (!CanInlinePropertyAccess(*type)) {
5319 lookup->NotFound();
5320 return false;
5321 } 5438 }
5322 // If we directly find a field, the access can be inlined.
5323 type->LookupDescriptor(NULL, *name, lookup);
5324 if (lookup->IsField()) return true;
5325
5326 if (!lookup_transition) return false;
5327
5328 type->LookupTransition(NULL, *name, lookup);
5329 return lookup->IsTransitionToField(*type) &&
5330 (type->unused_property_fields() > 0);
5331 }
5332
5333
5334 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
5335 HValue* object,
5336 Handle<String> name,
5337 HValue* value,
5338 Handle<Map> map) {
5339 // Handle a store to a known field.
5340 LookupResult lookup(isolate());
5341 if (ComputeStoreField(map, name, &lookup)) {
5342 HCheckMaps* checked_object = AddCheckMap(object, map);
5343 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
5344 }
5345
5346 // No luck, do a generic store.
5347 return BuildStoreNamedGeneric(object, name, value);
5348 }
5349
5350
5351 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad(
5352 PropertyAccessInfo* info) {
5353 if (!CanInlinePropertyAccess(*map_)) return false;
5354 5439
5355 if (!LookupDescriptor()) return false; 5440 if (!LookupDescriptor()) return false;
5356 5441
5357 if (!lookup_.IsFound()) { 5442 if (!lookup_.IsFound()) {
5358 return (!info->lookup_.IsFound() || info->has_holder()) && 5443 return (!info->lookup_.IsFound() || info->has_holder()) &&
5359 map_->prototype() == info->map_->prototype(); 5444 map()->prototype() == info->map()->prototype();
5360 } 5445 }
5361 5446
5362 // Mismatch if the other access info found the property in the prototype 5447 // Mismatch if the other access info found the property in the prototype
5363 // chain. 5448 // chain.
5364 if (info->has_holder()) return false; 5449 if (info->has_holder()) return false;
5365 5450
5366 if (lookup_.IsPropertyCallbacks()) { 5451 if (lookup_.IsPropertyCallbacks()) {
5367 return accessor_.is_identical_to(info->accessor_); 5452 return accessor_.is_identical_to(info->accessor_) &&
5453 api_holder_.is_identical_to(info->api_holder_);
5368 } 5454 }
5369 5455
5370 if (lookup_.IsConstant()) { 5456 if (lookup_.IsConstant()) {
5371 return constant_.is_identical_to(info->constant_); 5457 return constant_.is_identical_to(info->constant_);
5372 } 5458 }
5373 5459
5374 ASSERT(lookup_.IsField()); 5460 ASSERT(lookup_.IsField());
5375 if (!info->lookup_.IsField()) return false; 5461 if (!info->lookup_.IsField()) return false;
5376 5462
5377 Representation r = access_.representation(); 5463 Representation r = access_.representation();
5378 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; 5464 if (IsLoad()) {
5465 if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
5466 } else {
5467 if (!info->access_.representation().IsCompatibleForStore(r)) return false;
5468 }
5379 if (info->access_.offset() != access_.offset()) return false; 5469 if (info->access_.offset() != access_.offset()) return false;
5380 if (info->access_.IsInobject() != access_.IsInobject()) return false; 5470 if (info->access_.IsInobject() != access_.IsInobject()) return false;
5381 info->GeneralizeRepresentation(r); 5471 info->GeneralizeRepresentation(r);
5382 return true; 5472 return true;
5383 } 5473 }
5384 5474
5385 5475
5386 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { 5476 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
5387 map_->LookupDescriptor(NULL, *name_, &lookup_); 5477 if (!type_->IsClass()) return true;
5388 return LoadResult(map_); 5478 map()->LookupDescriptor(NULL, *name_, &lookup_);
5479 return LoadResult(map());
5389 } 5480 }
5390 5481
5391 5482
5392 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { 5483 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
5484 if (!IsLoad() && lookup_.IsProperty() &&
5485 (lookup_.IsReadOnly() || !lookup_.IsCacheable())) {
5486 return false;
5487 }
5488
5393 if (lookup_.IsField()) { 5489 if (lookup_.IsField()) {
5394 access_ = HObjectAccess::ForField(map, &lookup_, name_); 5490 access_ = HObjectAccess::ForField(map, &lookup_, name_);
5395 } else if (lookup_.IsPropertyCallbacks()) { 5491 } else if (lookup_.IsPropertyCallbacks()) {
5396 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); 5492 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
5397 if (!callback->IsAccessorPair()) return false; 5493 if (!callback->IsAccessorPair()) return false;
5398 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); 5494 Object* raw_accessor = IsLoad()
5399 if (!getter->IsJSFunction()) return false; 5495 ? Handle<AccessorPair>::cast(callback)->getter()
5400 Handle<JSFunction> accessor = handle(JSFunction::cast(getter)); 5496 : Handle<AccessorPair>::cast(callback)->setter();
5401 CallOptimization call_optimization(accessor); 5497 if (!raw_accessor->IsJSFunction()) return false;
5402 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. 5498 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
5403 if (call_optimization.is_simple_api_call()) return false; 5499 if (accessor->shared()->IsApiFunction()) {
5500 CallOptimization call_optimization(accessor);
5501 if (!call_optimization.is_simple_api_call()) return false;
5502 CallOptimization::HolderLookup holder_lookup;
5503 api_holder_ = call_optimization.LookupHolderOfExpectedType(
5504 map, &holder_lookup);
5505 switch (holder_lookup) {
5506 case CallOptimization::kHolderNotFound:
5507 return false;
5508 case CallOptimization::kHolderIsReceiver:
5509 case CallOptimization::kHolderFound:
5510 break;
5511 }
5512 }
5404 accessor_ = accessor; 5513 accessor_ = accessor;
5405 } else if (lookup_.IsConstant()) { 5514 } else if (lookup_.IsConstant()) {
5406 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); 5515 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
5407 } 5516 }
5408 5517
5409 return true; 5518 return true;
5410 } 5519 }
5411 5520
5412 5521
5413 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { 5522 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
5414 Handle<Map> map = map_; 5523 Handle<Map> map = this->map();
5524
5415 while (map->prototype()->IsJSObject()) { 5525 while (map->prototype()->IsJSObject()) {
5416 holder_ = handle(JSObject::cast(map->prototype())); 5526 holder_ = handle(JSObject::cast(map->prototype()));
5417 if (holder_->map()->is_deprecated()) { 5527 if (holder_->map()->is_deprecated()) {
5418 JSObject::TryMigrateInstance(holder_); 5528 JSObject::TryMigrateInstance(holder_);
5419 } 5529 }
5420 map = Handle<Map>(holder_->map()); 5530 map = Handle<Map>(holder_->map());
5421 if (!CanInlinePropertyAccess(*map)) { 5531 if (!CanInlinePropertyAccess(ToType(map))) {
5422 lookup_.NotFound(); 5532 lookup_.NotFound();
5423 return false; 5533 return false;
5424 } 5534 }
5425 map->LookupDescriptor(*holder_, *name_, &lookup_); 5535 map->LookupDescriptor(*holder_, *name_, &lookup_);
5426 if (lookup_.IsFound()) return LoadResult(map); 5536 if (lookup_.IsFound()) return LoadResult(map);
5427 } 5537 }
5428 lookup_.NotFound(); 5538 lookup_.NotFound();
5429 return true; 5539 return true;
5430 } 5540 }
5431 5541
5432 5542
5433 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { 5543 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
5434 if (!CanInlinePropertyAccess(*map_)) return IsStringLength(); 5544 if (!CanInlinePropertyAccess(type_)) return false;
5435 if (IsJSObjectFieldAccessor()) return true; 5545 if (IsJSObjectFieldAccessor()) return IsLoad();
5436 if (!LookupDescriptor()) return false; 5546 if (!LookupDescriptor()) return false;
5437 if (lookup_.IsFound()) return true; 5547 if (lookup_.IsFound()) {
5438 return LookupInPrototypes(); 5548 if (IsLoad()) return true;
5549 return !lookup_.IsReadOnly() && lookup_.IsCacheable();
5550 }
5551 if (!LookupInPrototypes()) return false;
5552 if (IsLoad()) return true;
5553
5554 if (lookup_.IsPropertyCallbacks()) return true;
5555 Handle<Map> map = this->map();
5556 map->LookupTransition(NULL, *name_, &lookup_);
5557 if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) {
5558 return true;
5559 }
5560 return false;
5439 } 5561 }
5440 5562
5441 5563
5442 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( 5564 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
5443 SmallMapList* types) { 5565 SmallMapList* types) {
5444 ASSERT(map_.is_identical_to(types->first())); 5566 ASSERT(type_->Is(ToType(types->first())));
5445 if (!CanLoadMonomorphic()) return false; 5567 if (!CanAccessMonomorphic()) return false;
5568 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
5446 if (types->length() > kMaxLoadPolymorphism) return false; 5569 if (types->length() > kMaxLoadPolymorphism) return false;
5447 5570
5448 if (IsStringLength()) { 5571 HObjectAccess access = HObjectAccess::ForMap(); // bogus default
5572 if (GetJSObjectFieldAccess(&access)) {
5449 for (int i = 1; i < types->length(); ++i) { 5573 for (int i = 1; i < types->length(); ++i) {
5450 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; 5574 PropertyAccessInfo test_info(
5575 builder_, access_type_, ToType(types->at(i)), name_);
5576 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default
5577 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
5578 if (!access.Equals(test_access)) return false;
5451 } 5579 }
5452 return true; 5580 return true;
5453 } 5581 }
5454 5582
5455 if (IsArrayLength()) { 5583 // Currently only handle Type::Number as a polymorphic case.
5456 bool is_fast = IsFastElementsKind(map_->elements_kind()); 5584 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5457 for (int i = 1; i < types->length(); ++i) { 5585 // instruction.
5458 Handle<Map> test_map = types->at(i); 5586 if (type_->Is(Type::Number())) return false;
5459 if (test_map->instance_type() != JS_ARRAY_TYPE) return false;
5460 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) {
5461 return false;
5462 }
5463 }
5464 return true;
5465 }
5466 5587
5467 if (IsJSObjectFieldAccessor()) { 5588 // Multiple maps cannot transition to the same target map.
5468 InstanceType instance_type = map_->instance_type(); 5589 ASSERT(!IsLoad() || !lookup_.IsTransition());
5469 for (int i = 1; i < types->length(); ++i) { 5590 if (lookup_.IsTransition() && types->length() > 1) return false;
5470 if (types->at(i)->instance_type() != instance_type) return false;
5471 }
5472 return true;
5473 }
5474 5591
5475 for (int i = 1; i < types->length(); ++i) { 5592 for (int i = 1; i < types->length(); ++i) {
5476 PropertyAccessInfo test_info(isolate(), types->at(i), name_); 5593 PropertyAccessInfo test_info(
5477 if (!test_info.IsCompatibleForLoad(this)) return false; 5594 builder_, access_type_, ToType(types->at(i)), name_);
5595 if (!test_info.IsCompatible(this)) return false;
5478 } 5596 }
5479 5597
5480 return true; 5598 return true;
5481 } 5599 }
5482 5600
5483 5601
5484 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( 5602 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) {
5603 return type->Is(Type::NumberOrString()) &&
5604 target->shared()->is_classic_mode() &&
5605 !target->shared()->native();
5606 }
5607
5608
5609 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
5485 PropertyAccessInfo* info, 5610 PropertyAccessInfo* info,
5486 HValue* object, 5611 HValue* object,
5487 HInstruction* checked_object, 5612 HValue* checked_object,
5613 HValue* value,
5488 BailoutId ast_id, 5614 BailoutId ast_id,
5489 BailoutId return_id, 5615 BailoutId return_id,
5490 bool can_inline_accessor) { 5616 bool can_inline_accessor) {
5491 5617
5492 HObjectAccess access = HObjectAccess::ForMap(); // bogus default 5618 HObjectAccess access = HObjectAccess::ForMap(); // bogus default
5493 if (info->GetJSObjectFieldAccess(&access)) { 5619 if (info->GetJSObjectFieldAccess(&access)) {
5494 return New<HLoadNamedField>(checked_object, access); 5620 ASSERT(info->IsLoad());
5621 return New<HLoadNamedField>(object, checked_object, access);
5495 } 5622 }
5496 5623
5497 HValue* checked_holder = checked_object; 5624 HValue* checked_holder = checked_object;
5498 if (info->has_holder()) { 5625 if (info->has_holder()) {
5499 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); 5626 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
5500 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); 5627 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
5501 } 5628 }
5502 5629
5503 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); 5630 if (!info->lookup()->IsFound()) {
5631 ASSERT(info->IsLoad());
5632 return graph()->GetConstantUndefined();
5633 }
5504 5634
5505 if (info->lookup()->IsField()) { 5635 if (info->lookup()->IsField()) {
5506 return BuildLoadNamedField(checked_holder, info->access()); 5636 if (info->IsLoad()) {
5637 return BuildLoadNamedField(info, checked_holder);
5638 } else {
5639 return BuildStoreNamedField(info, checked_object, value);
5640 }
5641 }
5642
5643 if (info->lookup()->IsTransition()) {
5644 ASSERT(!info->IsLoad());
5645 return BuildStoreNamedField(info, checked_object, value);
5507 } 5646 }
5508 5647
5509 if (info->lookup()->IsPropertyCallbacks()) { 5648 if (info->lookup()->IsPropertyCallbacks()) {
5510 Push(checked_object); 5649 Push(checked_object);
5511 if (FLAG_inline_accessors && 5650 int argument_count = 1;
5512 can_inline_accessor && 5651 if (!info->IsLoad()) {
5513 TryInlineGetter(info->accessor(), ast_id, return_id)) { 5652 argument_count = 2;
5514 return NULL; 5653 Push(value);
5515 } 5654 }
5516 Add<HPushArgument>(Pop()); 5655
5517 return BuildCallConstantFunction(info->accessor(), 1); 5656 if (NeedsWrappingFor(info->type(), info->accessor())) {
5657 HValue* function = Add<HConstant>(info->accessor());
5658 PushArgumentsFromEnvironment(argument_count);
5659 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
5660 } else if (FLAG_inline_accessors && can_inline_accessor) {
5661 bool success = info->IsLoad()
5662 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
5663 : TryInlineSetter(
5664 info->accessor(), info->map(), ast_id, return_id, value);
5665 if (success) return NULL;
5666 }
5667
5668 PushArgumentsFromEnvironment(argument_count);
5669 return BuildCallConstantFunction(info->accessor(), argument_count);
5518 } 5670 }
5519 5671
5520 ASSERT(info->lookup()->IsConstant()); 5672 ASSERT(info->lookup()->IsConstant());
5521 return New<HConstant>(info->constant()); 5673 if (info->IsLoad()) {
5674 return New<HConstant>(info->constant());
5675 } else {
5676 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
5677 }
5522 } 5678 }
5523 5679
5524 5680
5525 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 5681 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
5682 PropertyAccessType access_type,
5526 BailoutId ast_id, 5683 BailoutId ast_id,
5527 BailoutId return_id, 5684 BailoutId return_id,
5528 HValue* object, 5685 HValue* object,
5686 HValue* value,
5529 SmallMapList* types, 5687 SmallMapList* types,
5530 Handle<String> name) { 5688 Handle<String> name) {
5531 // Something did not match; must use a polymorphic load. 5689 // Something did not match; must use a polymorphic load.
5532 int count = 0; 5690 int count = 0;
5533 HBasicBlock* join = NULL; 5691 HBasicBlock* join = NULL;
5692 HBasicBlock* number_block = NULL;
5693 bool handled_string = false;
5694
5695 bool handle_smi = false;
5696 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
5534 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 5697 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5535 PropertyAccessInfo info(isolate(), types->at(i), name); 5698 PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
5536 if (info.CanLoadMonomorphic()) { 5699 if (info.type()->Is(Type::String())) {
5537 if (count == 0) { 5700 if (handled_string) continue;
5701 handled_string = true;
5702 }
5703 if (info.CanAccessMonomorphic()) {
5704 count++;
5705 if (info.type()->Is(Type::Number())) {
5706 handle_smi = true;
5707 break;
5708 }
5709 }
5710 }
5711
5712 count = 0;
5713 HControlInstruction* smi_check = NULL;
5714 handled_string = false;
5715
5716 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5717 PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
5718 if (info.type()->Is(Type::String())) {
5719 if (handled_string) continue;
5720 handled_string = true;
5721 }
5722 if (!info.CanAccessMonomorphic()) continue;
5723
5724 if (count == 0) {
5725 join = graph()->CreateBasicBlock();
5726 if (handle_smi) {
5727 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
5728 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
5729 number_block = graph()->CreateBasicBlock();
5730 smi_check = New<HIsSmiAndBranch>(
5731 object, empty_smi_block, not_smi_block);
5732 FinishCurrentBlock(smi_check);
5733 GotoNoSimulate(empty_smi_block, number_block);
5734 set_current_block(not_smi_block);
5735 } else {
5538 BuildCheckHeapObject(object); 5736 BuildCheckHeapObject(object);
5539 join = graph()->CreateBasicBlock();
5540 } 5737 }
5541 ++count; 5738 }
5542 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5739 ++count;
5543 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5740 HBasicBlock* if_true = graph()->CreateBasicBlock();
5544 HCompareMap* compare = New<HCompareMap>( 5741 HBasicBlock* if_false = graph()->CreateBasicBlock();
5545 object, info.map(), if_true, if_false); 5742 HUnaryControlInstruction* compare;
5546 FinishCurrentBlock(compare);
5547 5743
5548 set_current_block(if_true); 5744 HValue* dependency;
5745 if (info.type()->Is(Type::Number())) {
5746 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
5747 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
5748 dependency = smi_check;
5749 } else if (info.type()->Is(Type::String())) {
5750 compare = New<HIsStringAndBranch>(object, if_true, if_false);
5751 dependency = compare;
5752 } else {
5753 compare = New<HCompareMap>(object, info.map(), if_true, if_false);
5754 dependency = compare;
5755 }
5756 FinishCurrentBlock(compare);
5549 5757
5550 HInstruction* load = BuildLoadMonomorphic( 5758 if (info.type()->Is(Type::Number())) {
5551 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining); 5759 GotoNoSimulate(if_true, number_block);
5552 if (load == NULL) { 5760 if_true = number_block;
5553 if (HasStackOverflow()) return; 5761 }
5554 } else {
5555 if (!load->IsLinked()) {
5556 AddInstruction(load);
5557 }
5558 if (!ast_context()->IsEffect()) Push(load);
5559 }
5560 5762
5561 if (current_block() != NULL) Goto(join); 5763 set_current_block(if_true);
5562 set_current_block(if_false); 5764
5765 HInstruction* access = BuildMonomorphicAccess(
5766 &info, object, dependency, value, ast_id,
5767 return_id, FLAG_polymorphic_inlining);
5768
5769 HValue* result = NULL;
5770 switch (access_type) {
5771 case LOAD:
5772 result = access;
5773 break;
5774 case STORE:
5775 result = value;
5776 break;
5563 } 5777 }
5778
5779 if (access == NULL) {
5780 if (HasStackOverflow()) return;
5781 } else {
5782 if (!access->IsLinked()) AddInstruction(access);
5783 if (!ast_context()->IsEffect()) Push(result);
5784 }
5785
5786 if (current_block() != NULL) Goto(join);
5787 set_current_block(if_false);
5564 } 5788 }
5565 5789
5566 // Finish up. Unconditionally deoptimize if we've handled all the maps we 5790 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5567 // know about and do not want to handle ones we've never seen. Otherwise 5791 // know about and do not want to handle ones we've never seen. Otherwise
5568 // use a generic IC. 5792 // use a generic IC.
5569 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 5793 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5570 // Because the deopt may be the only path in the polymorphic load, make sure 5794 FinishExitWithHardDeoptimization("Uknown map in polymorphic access");
5571 // that the environment stack matches the depth on deopt that it otherwise
5572 // would have had after a successful load.
5573 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
5574 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
5575 } else { 5795 } else {
5576 HInstruction* load = Add<HLoadNamedGeneric>(object, name); 5796 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value);
5577 if (!ast_context()->IsEffect()) Push(load); 5797 AddInstruction(instr);
5798 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
5578 5799
5579 if (join != NULL) { 5800 if (join != NULL) {
5580 Goto(join); 5801 Goto(join);
5581 } else { 5802 } else {
5582 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5803 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5583 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 5804 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
5584 return; 5805 return;
5585 } 5806 }
5586 } 5807 }
5587 5808
5588 ASSERT(join != NULL); 5809 ASSERT(join != NULL);
5589 join->SetJoinId(ast_id); 5810 if (join->HasPredecessor()) {
5590 set_current_block(join); 5811 join->SetJoinId(ast_id);
5591 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 5812 set_current_block(join);
5592 } 5813 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
5593
5594
5595 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
5596 BailoutId assignment_id,
5597 HValue* object,
5598 HValue* value,
5599 SmallMapList* types,
5600 Handle<String> name) {
5601 // Use monomorphic store if property lookup results in the same field index
5602 // for all maps. Requires special map check on the set of all handled maps.
5603 if (types->length() > kMaxStorePolymorphism) return false;
5604
5605 LookupResult lookup(isolate());
5606 int count;
5607 Representation representation = Representation::None();
5608 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
5609 for (count = 0; count < types->length(); ++count) {
5610 Handle<Map> map = types->at(count);
5611 // Pass false to ignore transitions.
5612 if (!ComputeStoreField(map, name, &lookup, false)) break;
5613 ASSERT(!map->is_observed());
5614
5615 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
5616 Representation new_representation = new_access.representation();
5617
5618 if (count == 0) {
5619 // First time through the loop; set access and representation.
5620 access = new_access;
5621 representation = new_representation;
5622 } else if (!representation.IsCompatibleForStore(new_representation)) {
5623 // Representations did not match.
5624 break;
5625 } else if (access.offset() != new_access.offset()) {
5626 // Offsets did not match.
5627 break;
5628 } else if (access.IsInobject() != new_access.IsInobject()) {
5629 // In-objectness did not match.
5630 break;
5631 }
5632 }
5633
5634 if (count != types->length()) return false;
5635
5636 // Everything matched; can use monomorphic store.
5637 BuildCheckHeapObject(object);
5638 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
5639 HInstruction* store;
5640 CHECK_ALIVE_OR_RETURN(
5641 store = BuildStoreNamedField(
5642 checked_object, name, value, types->at(count - 1), &lookup),
5643 true);
5644 if (!ast_context()->IsEffect()) Push(value);
5645 AddInstruction(store);
5646 Add<HSimulate>(assignment_id);
5647 if (!ast_context()->IsEffect()) Drop(1);
5648 ast_context()->ReturnValue(value);
5649 return true;
5650 }
5651
5652
5653 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
5654 BailoutId assignment_id,
5655 HValue* object,
5656 HValue* value,
5657 SmallMapList* types,
5658 Handle<String> name) {
5659 if (TryStorePolymorphicAsMonomorphic(
5660 assignment_id, object, value, types, name)) {
5661 return;
5662 }
5663
5664 // TODO(ager): We should recognize when the prototype chains for different
5665 // maps are identical. In that case we can avoid repeatedly generating the
5666 // same prototype map checks.
5667 int count = 0;
5668 HBasicBlock* join = NULL;
5669 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
5670 Handle<Map> map = types->at(i);
5671 LookupResult lookup(isolate());
5672 if (ComputeStoreField(map, name, &lookup)) {
5673 if (count == 0) {
5674 BuildCheckHeapObject(object);
5675 join = graph()->CreateBasicBlock();
5676 }
5677 ++count;
5678 HBasicBlock* if_true = graph()->CreateBasicBlock();
5679 HBasicBlock* if_false = graph()->CreateBasicBlock();
5680 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false);
5681 FinishCurrentBlock(compare);
5682
5683 set_current_block(if_true);
5684 HInstruction* instr;
5685 CHECK_ALIVE(instr = BuildStoreNamedField(
5686 compare, name, value, map, &lookup));
5687 // Goto will add the HSimulate for the store.
5688 AddInstruction(instr);
5689 if (!ast_context()->IsEffect()) Push(value);
5690 Goto(join);
5691
5692 set_current_block(if_false);
5693 }
5694 }
5695
5696 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5697 // know about and do not want to handle ones we've never seen. Otherwise
5698 // use a generic IC.
5699 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5700 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
5701 } else { 5814 } else {
5702 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 5815 set_current_block(NULL);
5703 AddInstruction(instr);
5704
5705 if (join != NULL) {
5706 if (!ast_context()->IsEffect()) {
5707 Push(value);
5708 }
5709 Goto(join);
5710 } else {
5711 // The HSimulate for the store should not see the stored value in
5712 // effect contexts (it is not materialized at expr->id() in the
5713 // unoptimized code).
5714 if (instr->HasObservableSideEffects()) {
5715 if (ast_context()->IsEffect()) {
5716 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
5717 } else {
5718 Push(value);
5719 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
5720 Drop(1);
5721 }
5722 }
5723 return ast_context()->ReturnValue(value);
5724 }
5725 }
5726
5727 ASSERT(join != NULL);
5728 join->SetJoinId(assignment_id);
5729 set_current_block(join);
5730 if (!ast_context()->IsEffect()) {
5731 ast_context()->ReturnValue(Pop());
5732 } 5816 }
5733 } 5817 }
5734 5818
5735 5819
5736 static bool ComputeReceiverTypes(Expression* expr, 5820 static bool ComputeReceiverTypes(Expression* expr,
5737 HValue* receiver, 5821 HValue* receiver,
5738 SmallMapList** t) { 5822 SmallMapList** t,
5823 Zone* zone) {
5739 SmallMapList* types = expr->GetReceiverTypes(); 5824 SmallMapList* types = expr->GetReceiverTypes();
5740 *t = types; 5825 *t = types;
5741 bool monomorphic = expr->IsMonomorphic(); 5826 bool monomorphic = expr->IsMonomorphic();
5742 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { 5827 if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
5743 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); 5828 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
5744 types->FilterForPossibleTransitions(root_map); 5829 types->FilterForPossibleTransitions(root_map);
5745 monomorphic = types->length() == 1; 5830 monomorphic = types->length() == 1;
5746 } 5831 }
5747 return monomorphic && CanInlinePropertyAccess(*types->first()); 5832 return monomorphic && CanInlinePropertyAccess(
5833 IC::MapToType<Type>(types->first(), zone));
5748 } 5834 }
5749 5835
5750 5836
5837 static bool AreStringTypes(SmallMapList* types) {
5838 for (int i = 0; i < types->length(); i++) {
5839 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
5840 }
5841 return true;
5842 }
5843
5844
5751 void HOptimizedGraphBuilder::BuildStore(Expression* expr, 5845 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
5752 Property* prop, 5846 Property* prop,
5753 BailoutId ast_id, 5847 BailoutId ast_id,
5754 BailoutId return_id, 5848 BailoutId return_id,
5755 bool is_uninitialized) { 5849 bool is_uninitialized) {
5756 HValue* value = environment()->ExpressionStackAt(0);
5757
5758 if (!prop->key()->IsPropertyName()) { 5850 if (!prop->key()->IsPropertyName()) {
5759 // Keyed store. 5851 // Keyed store.
5852 HValue* value = environment()->ExpressionStackAt(0);
5760 HValue* key = environment()->ExpressionStackAt(1); 5853 HValue* key = environment()->ExpressionStackAt(1);
5761 HValue* object = environment()->ExpressionStackAt(2); 5854 HValue* object = environment()->ExpressionStackAt(2);
5762 bool has_side_effects = false; 5855 bool has_side_effects = false;
5763 HandleKeyedElementAccess(object, key, value, expr, 5856 HandleKeyedElementAccess(object, key, value, expr,
5764 true, // is_store 5857 STORE, &has_side_effects);
5765 &has_side_effects);
5766 Drop(3); 5858 Drop(3);
5767 Push(value); 5859 Push(value);
5768 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); 5860 Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
5769 return ast_context()->ReturnValue(Pop()); 5861 return ast_context()->ReturnValue(Pop());
5770 } 5862 }
5771 5863
5772 // Named store. 5864 // Named store.
5773 HValue* object = environment()->ExpressionStackAt(1); 5865 HValue* value = Pop();
5774 5866 HValue* object = Pop();
5775 if (is_uninitialized) {
5776 Add<HDeoptimize>("Insufficient type feedback for property assignment",
5777 Deoptimizer::SOFT);
5778 }
5779 5867
5780 Literal* key = prop->key()->AsLiteral(); 5868 Literal* key = prop->key()->AsLiteral();
5781 Handle<String> name = Handle<String>::cast(key->value()); 5869 Handle<String> name = Handle<String>::cast(key->value());
5782 ASSERT(!name.is_null()); 5870 ASSERT(!name.is_null());
5783 5871
5784 HInstruction* instr = NULL; 5872 HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr,
5785 5873 object, name, value, is_uninitialized);
5786 SmallMapList* types; 5874 if (instr == NULL) return;
5787 bool monomorphic = ComputeReceiverTypes(expr, object, &types);
5788
5789 if (monomorphic) {
5790 Handle<Map> map = types->first();
5791 Handle<JSFunction> setter;
5792 Handle<JSObject> holder;
5793 if (LookupSetter(map, name, &setter, &holder)) {
5794 AddCheckConstantFunction(holder, object, map);
5795 if (FLAG_inline_accessors &&
5796 TryInlineSetter(setter, ast_id, return_id, value)) {
5797 return;
5798 }
5799 Drop(2);
5800 Add<HPushArgument>(object);
5801 Add<HPushArgument>(value);
5802 instr = BuildCallConstantFunction(setter, 2);
5803 } else {
5804 Drop(2);
5805 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
5806 name,
5807 value,
5808 map));
5809 }
5810 } else if (types != NULL && types->length() > 1) {
5811 Drop(2);
5812 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name);
5813 } else {
5814 Drop(2);
5815 instr = BuildStoreNamedGeneric(object, name, value);
5816 }
5817 5875
5818 if (!ast_context()->IsEffect()) Push(value); 5876 if (!ast_context()->IsEffect()) Push(value);
5819 AddInstruction(instr); 5877 AddInstruction(instr);
5820 if (instr->HasObservableSideEffects()) { 5878 if (instr->HasObservableSideEffects()) {
5821 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5879 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5822 } 5880 }
5823 if (!ast_context()->IsEffect()) Drop(1); 5881 if (!ast_context()->IsEffect()) Drop(1);
5824 return ast_context()->ReturnValue(value); 5882 return ast_context()->ReturnValue(value);
5825 } 5883 }
5826 5884
(...skipping 12 matching lines...) Expand all
5839 5897
5840 5898
5841 // Because not every expression has a position and there is not common 5899 // Because not every expression has a position and there is not common
5842 // superclass of Assignment and CountOperation, we cannot just pass the 5900 // superclass of Assignment and CountOperation, we cannot just pass the
5843 // owning expression instead of position and ast_id separately. 5901 // owning expression instead of position and ast_id separately.
5844 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( 5902 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
5845 Variable* var, 5903 Variable* var,
5846 HValue* value, 5904 HValue* value,
5847 BailoutId ast_id) { 5905 BailoutId ast_id) {
5848 LookupResult lookup(isolate()); 5906 LookupResult lookup(isolate());
5849 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 5907 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, STORE);
5850 if (type == kUseCell) { 5908 if (type == kUseCell) {
5851 Handle<GlobalObject> global(current_info()->global_object()); 5909 Handle<GlobalObject> global(current_info()->global_object());
5852 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 5910 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
5853 if (cell->type()->IsConstant()) { 5911 if (cell->type()->IsConstant()) {
5854 IfBuilder builder(this); 5912 Handle<Object> constant = cell->type()->AsConstant();
5855 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); 5913 if (value->IsConstant()) {
5856 if (cell->type()->AsConstant()->IsNumber()) { 5914 HConstant* c_value = HConstant::cast(value);
5857 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); 5915 if (!constant.is_identical_to(c_value->handle(isolate()))) {
5916 Add<HDeoptimize>("Constant global variable assignment",
5917 Deoptimizer::EAGER);
5918 }
5858 } else { 5919 } else {
5859 builder.If<HCompareObjectEqAndBranch>(value, constant); 5920 HValue* c_constant = Add<HConstant>(constant);
5921 IfBuilder builder(this);
5922 if (constant->IsNumber()) {
5923 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
5924 } else {
5925 builder.If<HCompareObjectEqAndBranch>(value, c_constant);
5926 }
5927 builder.Then();
5928 builder.Else();
5929 Add<HDeoptimize>("Constant global variable assignment",
5930 Deoptimizer::EAGER);
5931 builder.End();
5860 } 5932 }
5861 builder.Then();
5862 builder.Else();
5863 Add<HDeoptimize>("Constant global variable assignment",
5864 Deoptimizer::EAGER);
5865 builder.End();
5866 } 5933 }
5867 HInstruction* instr = 5934 HInstruction* instr =
5868 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); 5935 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
5869 if (instr->HasObservableSideEffects()) { 5936 if (instr->HasObservableSideEffects()) {
5870 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5937 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5871 } 5938 }
5872 } else { 5939 } else {
5873 HGlobalObject* global_object = Add<HGlobalObject>(); 5940 HValue* global_object = Add<HLoadNamedField>(
5941 context(), static_cast<HValue*>(NULL),
5942 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
5874 HStoreNamedGeneric* instr = 5943 HStoreNamedGeneric* instr =
5875 Add<HStoreNamedGeneric>(global_object, var->name(), 5944 Add<HStoreNamedGeneric>(global_object, var->name(),
5876 value, function_strict_mode_flag()); 5945 value, function_strict_mode_flag());
5877 USE(instr); 5946 USE(instr);
5878 ASSERT(instr->HasObservableSideEffects()); 5947 ASSERT(instr->HasObservableSideEffects());
5879 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5948 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5880 } 5949 }
5881 } 5950 }
5882 5951
5883 5952
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
5969 CHECK_ALIVE(VisitForValue(prop->key())); 6038 CHECK_ALIVE(VisitForValue(prop->key()));
5970 key = Top(); 6039 key = Top();
5971 } 6040 }
5972 6041
5973 CHECK_ALIVE(PushLoad(prop, object, key)); 6042 CHECK_ALIVE(PushLoad(prop, object, key));
5974 6043
5975 CHECK_ALIVE(VisitForValue(expr->value())); 6044 CHECK_ALIVE(VisitForValue(expr->value()));
5976 HValue* right = Pop(); 6045 HValue* right = Pop();
5977 HValue* left = Pop(); 6046 HValue* left = Pop();
5978 6047
5979 Push(BuildBinaryOperation(operation, left, right)); 6048 Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
6049
5980 BuildStore(expr, prop, expr->id(), 6050 BuildStore(expr, prop, expr->id(),
5981 expr->AssignmentId(), expr->IsUninitialized()); 6051 expr->AssignmentId(), expr->IsUninitialized());
5982 } else { 6052 } else {
5983 return Bailout(kInvalidLhsInCompoundAssignment); 6053 return Bailout(kInvalidLhsInCompoundAssignment);
5984 } 6054 }
5985 } 6055 }
5986 6056
5987 6057
5988 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { 6058 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
5989 ASSERT(!HasStackOverflow()); 6059 ASSERT(!HasStackOverflow());
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
6120 ASSERT(!HasStackOverflow()); 6190 ASSERT(!HasStackOverflow());
6121 ASSERT(current_block() != NULL); 6191 ASSERT(current_block() != NULL);
6122 ASSERT(current_block()->HasPredecessor()); 6192 ASSERT(current_block()->HasPredecessor());
6123 // We don't optimize functions with invalid left-hand sides in 6193 // We don't optimize functions with invalid left-hand sides in
6124 // assignments, count operations, or for-in. Consequently throw can 6194 // assignments, count operations, or for-in. Consequently throw can
6125 // currently only occur in an effect context. 6195 // currently only occur in an effect context.
6126 ASSERT(ast_context()->IsEffect()); 6196 ASSERT(ast_context()->IsEffect());
6127 CHECK_ALIVE(VisitForValue(expr->exception())); 6197 CHECK_ALIVE(VisitForValue(expr->exception()));
6128 6198
6129 HValue* value = environment()->Pop(); 6199 HValue* value = environment()->Pop();
6130 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 6200 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
6131 Add<HThrow>(value); 6201 Add<HPushArgument>(value);
6202 Add<HCallRuntime>(isolate()->factory()->empty_string(),
6203 Runtime::FunctionForId(Runtime::kThrow), 1);
6132 Add<HSimulate>(expr->id()); 6204 Add<HSimulate>(expr->id());
6133 6205
6134 // If the throw definitely exits the function, we can finish with a dummy 6206 // If the throw definitely exits the function, we can finish with a dummy
6135 // control flow at this point. This is not the case if the throw is inside 6207 // control flow at this point. This is not the case if the throw is inside
6136 // an inlined function which may be replaced. 6208 // an inlined function which may be replaced.
6137 if (call_context() == NULL) { 6209 if (call_context() == NULL) {
6138 FinishExitCurrentBlock(New<HAbnormalExit>()); 6210 FinishExitCurrentBlock(New<HAbnormalExit>());
6139 } 6211 }
6140 } 6212 }
6141 6213
6142 6214
6143 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
6144 HObjectAccess access) {
6145 if (FLAG_track_double_fields && access.representation().IsDouble()) {
6146 // load the heap number
6147 HLoadNamedField* heap_number = Add<HLoadNamedField>(
6148 object, access.WithRepresentation(Representation::Tagged()));
6149 heap_number->set_type(HType::HeapNumber());
6150 // load the double value from it
6151 return New<HLoadNamedField>(
6152 heap_number, HObjectAccess::ForHeapNumberValue());
6153 }
6154 return New<HLoadNamedField>(object, access);
6155 }
6156
6157
6158 HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object,
6159 HObjectAccess access) {
6160 return AddInstruction(BuildLoadNamedField(object, access));
6161 }
6162
6163
6164 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) { 6215 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
6165 if (string->IsConstant()) { 6216 if (string->IsConstant()) {
6166 HConstant* c_string = HConstant::cast(string); 6217 HConstant* c_string = HConstant::cast(string);
6167 if (c_string->HasStringValue()) { 6218 if (c_string->HasStringValue()) {
6168 return Add<HConstant>(c_string->StringValue()->map()->instance_type()); 6219 return Add<HConstant>(c_string->StringValue()->map()->instance_type());
6169 } 6220 }
6170 } 6221 }
6171 return AddLoadNamedField( 6222 return Add<HLoadNamedField>(
6172 AddLoadNamedField(string, HObjectAccess::ForMap()), 6223 Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
6173 HObjectAccess::ForMapInstanceType()); 6224 HObjectAccess::ForMap()),
6225 static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
6174 } 6226 }
6175 6227
6176 6228
6177 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) { 6229 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
6178 if (string->IsConstant()) { 6230 if (string->IsConstant()) {
6179 HConstant* c_string = HConstant::cast(string); 6231 HConstant* c_string = HConstant::cast(string);
6180 if (c_string->HasStringValue()) { 6232 if (c_string->HasStringValue()) {
6181 return Add<HConstant>(c_string->StringValue()->length()); 6233 return Add<HConstant>(c_string->StringValue()->length());
6182 } 6234 }
6183 } 6235 }
6184 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); 6236 return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
6237 HObjectAccess::ForStringLength());
6185 } 6238 }
6186 6239
6187 6240
6188 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 6241 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
6242 PropertyAccessType access_type,
6189 HValue* object, 6243 HValue* object,
6190 Handle<String> name, 6244 Handle<String> name,
6191 Property* expr) { 6245 HValue* value,
6192 if (expr->IsUninitialized()) { 6246 bool is_uninitialized) {
6193 Add<HDeoptimize>("Insufficient type feedback for generic named load", 6247 if (is_uninitialized) {
6248 Add<HDeoptimize>("Insufficient type feedback for generic named access",
6194 Deoptimizer::SOFT); 6249 Deoptimizer::SOFT);
6195 } 6250 }
6196 return New<HLoadNamedGeneric>(object, name); 6251 if (access_type == LOAD) {
6252 return New<HLoadNamedGeneric>(object, name);
6253 } else {
6254 return New<HStoreNamedGeneric>(
6255 object, name, value, function_strict_mode_flag());
6256 }
6197 } 6257 }
6198 6258
6199 6259
6200 6260
6201 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 6261 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
6202 HValue* key) { 6262 PropertyAccessType access_type,
6203 return New<HLoadKeyedGeneric>(object, key); 6263 HValue* object,
6264 HValue* key,
6265 HValue* value) {
6266 if (access_type == LOAD) {
6267 return New<HLoadKeyedGeneric>(object, key);
6268 } else {
6269 return New<HStoreKeyedGeneric>(
6270 object, key, value, function_strict_mode_flag());
6271 }
6204 } 6272 }
6205 6273
6206 6274
6207 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { 6275 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
6208 // Loads from a "stock" fast holey double arrays can elide the hole check. 6276 // Loads from a "stock" fast holey double arrays can elide the hole check.
6209 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 6277 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
6210 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 6278 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
6211 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 6279 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
6212 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 6280 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
6213 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 6281 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
6214 BuildCheckPrototypeMaps(prototype, object_prototype); 6282 BuildCheckPrototypeMaps(prototype, object_prototype);
6215 load_mode = ALLOW_RETURN_HOLE; 6283 load_mode = ALLOW_RETURN_HOLE;
6216 graph()->MarkDependsOnEmptyArrayProtoElements(); 6284 graph()->MarkDependsOnEmptyArrayProtoElements();
6217 } 6285 }
6218 6286
6219 return load_mode; 6287 return load_mode;
6220 } 6288 }
6221 6289
6222 6290
6223 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( 6291 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
6224 HValue* object, 6292 HValue* object,
6225 HValue* key, 6293 HValue* key,
6226 HValue* val, 6294 HValue* val,
6227 HValue* dependency, 6295 HValue* dependency,
6228 Handle<Map> map, 6296 Handle<Map> map,
6229 bool is_store, 6297 PropertyAccessType access_type,
6230 KeyedAccessStoreMode store_mode) { 6298 KeyedAccessStoreMode store_mode) {
6231 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), 6299 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
6232 dependency); 6300 dependency);
6233 if (dependency) { 6301 if (dependency) {
6234 checked_object->ClearGVNFlag(kDependsOnElementsKind); 6302 checked_object->ClearDependsOnFlag(kElementsKind);
6235 } 6303 }
6236 6304
6237 if (is_store && map->prototype()->IsJSObject()) { 6305 if (access_type == STORE && map->prototype()->IsJSObject()) {
6238 // monomorphic stores need a prototype chain check because shape 6306 // monomorphic stores need a prototype chain check because shape
6239 // changes could allow callbacks on elements in the chain that 6307 // changes could allow callbacks on elements in the chain that
6240 // aren't compatible with monomorphic keyed stores. 6308 // aren't compatible with monomorphic keyed stores.
6241 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 6309 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
6242 Object* holder = map->prototype(); 6310 Object* holder = map->prototype();
6243 while (holder->GetPrototype(isolate())->IsJSObject()) { 6311 while (holder->GetPrototype(isolate())->IsJSObject()) {
6244 holder = holder->GetPrototype(isolate()); 6312 holder = holder->GetPrototype(isolate());
6245 } 6313 }
6246 ASSERT(holder->GetPrototype(isolate())->IsNull()); 6314 ASSERT(holder->GetPrototype(isolate())->IsNull());
6247 6315
6248 BuildCheckPrototypeMaps(prototype, 6316 BuildCheckPrototypeMaps(prototype,
6249 Handle<JSObject>(JSObject::cast(holder))); 6317 Handle<JSObject>(JSObject::cast(holder)));
6250 } 6318 }
6251 6319
6252 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); 6320 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
6253 return BuildUncheckedMonomorphicElementAccess( 6321 return BuildUncheckedMonomorphicElementAccess(
6254 checked_object, key, val, 6322 checked_object, key, val,
6255 map->instance_type() == JS_ARRAY_TYPE, 6323 map->instance_type() == JS_ARRAY_TYPE,
6256 map->elements_kind(), is_store, 6324 map->elements_kind(), access_type,
6257 load_mode, store_mode); 6325 load_mode, store_mode);
6258 } 6326 }
6259 6327
6260 6328
6261 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( 6329 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
6262 HValue* object, 6330 HValue* object,
6263 HValue* key, 6331 HValue* key,
6264 HValue* val, 6332 HValue* val,
6265 SmallMapList* maps) { 6333 SmallMapList* maps) {
6266 // For polymorphic loads of similar elements kinds (i.e. all tagged or all 6334 // For polymorphic loads of similar elements kinds (i.e. all tagged or all
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
6312 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps); 6380 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
6313 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS. 6381 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
6314 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS. 6382 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
6315 ElementsKind consolidated_elements_kind = has_seen_holey_elements 6383 ElementsKind consolidated_elements_kind = has_seen_holey_elements
6316 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind()) 6384 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
6317 : most_general_consolidated_map->elements_kind(); 6385 : most_general_consolidated_map->elements_kind();
6318 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 6386 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6319 checked_object, key, val, 6387 checked_object, key, val,
6320 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 6388 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
6321 consolidated_elements_kind, 6389 consolidated_elements_kind,
6322 false, NEVER_RETURN_HOLE, STANDARD_STORE); 6390 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
6323 return instr; 6391 return instr;
6324 } 6392 }
6325 6393
6326 6394
6327 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 6395 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
6328 HValue* object, 6396 HValue* object,
6329 HValue* key, 6397 HValue* key,
6330 HValue* val, 6398 HValue* val,
6331 SmallMapList* maps, 6399 SmallMapList* maps,
6332 bool is_store, 6400 PropertyAccessType access_type,
6333 KeyedAccessStoreMode store_mode, 6401 KeyedAccessStoreMode store_mode,
6334 bool* has_side_effects) { 6402 bool* has_side_effects) {
6335 *has_side_effects = false; 6403 *has_side_effects = false;
6336 BuildCheckHeapObject(object); 6404 BuildCheckHeapObject(object);
6337 6405
6338 if (!is_store) { 6406 if (access_type == LOAD) {
6339 HInstruction* consolidated_load = 6407 HInstruction* consolidated_load =
6340 TryBuildConsolidatedElementLoad(object, key, val, maps); 6408 TryBuildConsolidatedElementLoad(object, key, val, maps);
6341 if (consolidated_load != NULL) { 6409 if (consolidated_load != NULL) {
6342 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 6410 *has_side_effects |= consolidated_load->HasObservableSideEffects();
6343 return consolidated_load; 6411 return consolidated_load;
6344 } 6412 }
6345 } 6413 }
6346 6414
6347 // Elements_kind transition support. 6415 // Elements_kind transition support.
6348 MapHandleList transition_target(maps->length()); 6416 MapHandleList transition_target(maps->length());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
6381 } 6449 }
6382 6450
6383 // If only one map is left after transitioning, handle this case 6451 // If only one map is left after transitioning, handle this case
6384 // monomorphically. 6452 // monomorphically.
6385 ASSERT(untransitionable_maps.length() >= 1); 6453 ASSERT(untransitionable_maps.length() >= 1);
6386 if (untransitionable_maps.length() == 1) { 6454 if (untransitionable_maps.length() == 1) {
6387 Handle<Map> untransitionable_map = untransitionable_maps[0]; 6455 Handle<Map> untransitionable_map = untransitionable_maps[0];
6388 HInstruction* instr = NULL; 6456 HInstruction* instr = NULL;
6389 if (untransitionable_map->has_slow_elements_kind() || 6457 if (untransitionable_map->has_slow_elements_kind() ||
6390 !untransitionable_map->IsJSObjectMap()) { 6458 !untransitionable_map->IsJSObjectMap()) {
6391 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 6459 instr = AddInstruction(BuildKeyedGeneric(access_type, object, key, val));
6392 : BuildLoadKeyedGeneric(object, key));
6393 } else { 6460 } else {
6394 instr = BuildMonomorphicElementAccess( 6461 instr = BuildMonomorphicElementAccess(
6395 object, key, val, transition, untransitionable_map, is_store, 6462 object, key, val, transition, untransitionable_map, access_type,
6396 store_mode); 6463 store_mode);
6397 } 6464 }
6398 *has_side_effects |= instr->HasObservableSideEffects(); 6465 *has_side_effects |= instr->HasObservableSideEffects();
6399 return is_store ? NULL : instr; 6466 return access_type == STORE ? NULL : instr;
6400 } 6467 }
6401 6468
6402 HBasicBlock* join = graph()->CreateBasicBlock(); 6469 HBasicBlock* join = graph()->CreateBasicBlock();
6403 6470
6404 for (int i = 0; i < untransitionable_maps.length(); ++i) { 6471 for (int i = 0; i < untransitionable_maps.length(); ++i) {
6405 Handle<Map> map = untransitionable_maps[i]; 6472 Handle<Map> map = untransitionable_maps[i];
6406 if (!map->IsJSObjectMap()) continue; 6473 if (!map->IsJSObjectMap()) continue;
6407 ElementsKind elements_kind = map->elements_kind(); 6474 ElementsKind elements_kind = map->elements_kind();
6408 HBasicBlock* this_map = graph()->CreateBasicBlock(); 6475 HBasicBlock* this_map = graph()->CreateBasicBlock();
6409 HBasicBlock* other_map = graph()->CreateBasicBlock(); 6476 HBasicBlock* other_map = graph()->CreateBasicBlock();
6410 HCompareMap* mapcompare = 6477 HCompareMap* mapcompare =
6411 New<HCompareMap>(object, map, this_map, other_map); 6478 New<HCompareMap>(object, map, this_map, other_map);
6412 FinishCurrentBlock(mapcompare); 6479 FinishCurrentBlock(mapcompare);
6413 6480
6414 set_current_block(this_map); 6481 set_current_block(this_map);
6415 HInstruction* access = NULL; 6482 HInstruction* access = NULL;
6416 if (IsDictionaryElementsKind(elements_kind)) { 6483 if (IsDictionaryElementsKind(elements_kind)) {
6417 access = is_store 6484 access = AddInstruction(BuildKeyedGeneric(access_type, object, key, val));
6418 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
6419 : AddInstruction(BuildLoadKeyedGeneric(object, key));
6420 } else { 6485 } else {
6421 ASSERT(IsFastElementsKind(elements_kind) || 6486 ASSERT(IsFastElementsKind(elements_kind) ||
6422 IsExternalArrayElementsKind(elements_kind)); 6487 IsExternalArrayElementsKind(elements_kind));
6423 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); 6488 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
6424 // Happily, mapcompare is a checked object. 6489 // Happily, mapcompare is a checked object.
6425 access = BuildUncheckedMonomorphicElementAccess( 6490 access = BuildUncheckedMonomorphicElementAccess(
6426 mapcompare, key, val, 6491 mapcompare, key, val,
6427 map->instance_type() == JS_ARRAY_TYPE, 6492 map->instance_type() == JS_ARRAY_TYPE,
6428 elements_kind, is_store, 6493 elements_kind, access_type,
6429 load_mode, 6494 load_mode,
6430 store_mode); 6495 store_mode);
6431 } 6496 }
6432 *has_side_effects |= access->HasObservableSideEffects(); 6497 *has_side_effects |= access->HasObservableSideEffects();
6433 // The caller will use has_side_effects and add a correct Simulate. 6498 // The caller will use has_side_effects and add a correct Simulate.
6434 access->SetFlag(HValue::kHasNoObservableSideEffects); 6499 access->SetFlag(HValue::kHasNoObservableSideEffects);
6435 if (!is_store) { 6500 if (access_type == LOAD) {
6436 Push(access); 6501 Push(access);
6437 } 6502 }
6438 NoObservableSideEffectsScope scope(this); 6503 NoObservableSideEffectsScope scope(this);
6439 GotoNoSimulate(join); 6504 GotoNoSimulate(join);
6440 set_current_block(other_map); 6505 set_current_block(other_map);
6441 } 6506 }
6442 6507
6508 // Ensure that we visited at least one map above that goes to join. This is
6509 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
6510 // rather than joining the join block. If this becomes an issue, insert a
6511 // generic access in the case length() == 0.
6512 ASSERT(join->predecessors()->length() > 0);
6443 // Deopt if none of the cases matched. 6513 // Deopt if none of the cases matched.
6444 NoObservableSideEffectsScope scope(this); 6514 NoObservableSideEffectsScope scope(this);
6445 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", 6515 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access");
6446 join);
6447 set_current_block(join); 6516 set_current_block(join);
6448 return is_store ? NULL : Pop(); 6517 return access_type == STORE ? NULL : Pop();
6449 } 6518 }
6450 6519
6451 6520
6452 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( 6521 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
6453 HValue* obj, 6522 HValue* obj,
6454 HValue* key, 6523 HValue* key,
6455 HValue* val, 6524 HValue* val,
6456 Expression* expr, 6525 Expression* expr,
6457 bool is_store, 6526 PropertyAccessType access_type,
6458 bool* has_side_effects) { 6527 bool* has_side_effects) {
6459 ASSERT(!expr->IsPropertyName()); 6528 ASSERT(!expr->IsPropertyName());
6460 HInstruction* instr = NULL; 6529 HInstruction* instr = NULL;
6461 6530
6462 SmallMapList* types; 6531 SmallMapList* types;
6463 bool monomorphic = ComputeReceiverTypes(expr, obj, &types); 6532 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
6464 6533
6465 bool force_generic = false; 6534 bool force_generic = false;
6466 if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) { 6535 if (access_type == STORE &&
6536 (monomorphic || (types != NULL && !types->is_empty()))) {
6467 // Stores can't be mono/polymorphic if their prototype chain has dictionary 6537 // Stores can't be mono/polymorphic if their prototype chain has dictionary
6468 // elements. However a receiver map that has dictionary elements itself 6538 // elements. However a receiver map that has dictionary elements itself
6469 // should be left to normal mono/poly behavior (the other maps may benefit 6539 // should be left to normal mono/poly behavior (the other maps may benefit
6470 // from highly optimized stores). 6540 // from highly optimized stores).
6471 for (int i = 0; i < types->length(); i++) { 6541 for (int i = 0; i < types->length(); i++) {
6472 Handle<Map> current_map = types->at(i); 6542 Handle<Map> current_map = types->at(i);
6473 if (current_map->DictionaryElementsInPrototypeChainOnly()) { 6543 if (current_map->DictionaryElementsInPrototypeChainOnly()) {
6474 force_generic = true; 6544 force_generic = true;
6475 monomorphic = false; 6545 monomorphic = false;
6476 break; 6546 break;
6477 } 6547 }
6478 } 6548 }
6479 } 6549 }
6480 6550
6481 if (monomorphic) { 6551 if (monomorphic) {
6482 Handle<Map> map = types->first(); 6552 Handle<Map> map = types->first();
6483 if (map->has_slow_elements_kind()) { 6553 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
6484 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 6554 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val));
6485 : BuildLoadKeyedGeneric(obj, key);
6486 AddInstruction(instr);
6487 } else { 6555 } else {
6488 BuildCheckHeapObject(obj); 6556 BuildCheckHeapObject(obj);
6489 instr = BuildMonomorphicElementAccess( 6557 instr = BuildMonomorphicElementAccess(
6490 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); 6558 obj, key, val, NULL, map, access_type, expr->GetStoreMode());
6491 } 6559 }
6492 } else if (!force_generic && (types != NULL && !types->is_empty())) { 6560 } else if (!force_generic && (types != NULL && !types->is_empty())) {
6493 return HandlePolymorphicElementAccess( 6561 return HandlePolymorphicElementAccess(
6494 obj, key, val, types, is_store, 6562 obj, key, val, types, access_type,
6495 expr->GetStoreMode(), has_side_effects); 6563 expr->GetStoreMode(), has_side_effects);
6496 } else { 6564 } else {
6497 if (is_store) { 6565 if (access_type == STORE) {
6498 if (expr->IsAssignment() && 6566 if (expr->IsAssignment() &&
6499 expr->AsAssignment()->HasNoTypeInformation()) { 6567 expr->AsAssignment()->HasNoTypeInformation()) {
6500 Add<HDeoptimize>("Insufficient type feedback for keyed store", 6568 Add<HDeoptimize>("Insufficient type feedback for keyed store",
6501 Deoptimizer::SOFT); 6569 Deoptimizer::SOFT);
6502 } 6570 }
6503 instr = BuildStoreKeyedGeneric(obj, key, val);
6504 } else { 6571 } else {
6505 if (expr->AsProperty()->HasNoTypeInformation()) { 6572 if (expr->AsProperty()->HasNoTypeInformation()) {
6506 Add<HDeoptimize>("Insufficient type feedback for keyed load", 6573 Add<HDeoptimize>("Insufficient type feedback for keyed load",
6507 Deoptimizer::SOFT); 6574 Deoptimizer::SOFT);
6508 } 6575 }
6509 instr = BuildLoadKeyedGeneric(obj, key);
6510 } 6576 }
6511 AddInstruction(instr); 6577 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val));
6512 } 6578 }
6513 *has_side_effects = instr->HasObservableSideEffects(); 6579 *has_side_effects = instr->HasObservableSideEffects();
6514 return instr; 6580 return instr;
6515 } 6581 }
6516 6582
6517 6583
6518 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
6519 HValue* object,
6520 HValue* key,
6521 HValue* value) {
6522 return New<HStoreKeyedGeneric>(
6523 object,
6524 key,
6525 value,
6526 function_strict_mode_flag());
6527 }
6528
6529
6530 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { 6584 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
6531 // Outermost function already has arguments on the stack. 6585 // Outermost function already has arguments on the stack.
6532 if (function_state()->outer() == NULL) return; 6586 if (function_state()->outer() == NULL) return;
6533 6587
6534 if (function_state()->arguments_pushed()) return; 6588 if (function_state()->arguments_pushed()) return;
6535 6589
6536 // Push arguments when entering inlined function. 6590 // Push arguments when entering inlined function.
6537 HEnterInlined* entry = function_state()->entry(); 6591 HEnterInlined* entry = function_state()->entry();
6538 entry->set_arguments_pushed(); 6592 entry->set_arguments_pushed();
6539 6593
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
6597 HInstruction* length = Add<HConstant>(argument_count); 6651 HInstruction* length = Add<HConstant>(argument_count);
6598 HInstruction* checked_key = Add<HBoundsCheck>(key, length); 6652 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
6599 result = New<HAccessArgumentsAt>(elements, length, checked_key); 6653 result = New<HAccessArgumentsAt>(elements, length, checked_key);
6600 } 6654 }
6601 } 6655 }
6602 ast_context()->ReturnInstruction(result, expr->id()); 6656 ast_context()->ReturnInstruction(result, expr->id());
6603 return true; 6657 return true;
6604 } 6658 }
6605 6659
6606 6660
6661 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess(
6662 PropertyAccessType access,
6663 BailoutId ast_id,
6664 BailoutId return_id,
6665 Expression* expr,
6666 HValue* object,
6667 Handle<String> name,
6668 HValue* value,
6669 bool is_uninitialized) {
6670 SmallMapList* types;
6671 ComputeReceiverTypes(expr, object, &types, zone());
6672 ASSERT(types != NULL);
6673
6674 if (types->length() > 0) {
6675 PropertyAccessInfo info(this, access, ToType(types->first()), name);
6676 if (!info.CanAccessAsMonomorphic(types)) {
6677 HandlePolymorphicNamedFieldAccess(
6678 access, ast_id, return_id, object, value, types, name);
6679 return NULL;
6680 }
6681
6682 HValue* checked_object;
6683 // Type::Number() is only supported by polymorphic load/call handling.
6684 ASSERT(!info.type()->Is(Type::Number()));
6685 BuildCheckHeapObject(object);
6686 if (AreStringTypes(types)) {
6687 checked_object =
6688 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
6689 } else {
6690 checked_object = Add<HCheckMaps>(object, types);
6691 }
6692 return BuildMonomorphicAccess(
6693 &info, object, checked_object, value, ast_id, return_id);
6694 }
6695
6696 return BuildNamedGeneric(access, object, name, value, is_uninitialized);
6697 }
6698
6699
6607 void HOptimizedGraphBuilder::PushLoad(Property* expr, 6700 void HOptimizedGraphBuilder::PushLoad(Property* expr,
6608 HValue* object, 6701 HValue* object,
6609 HValue* key) { 6702 HValue* key) {
6610 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 6703 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
6611 Push(object); 6704 Push(object);
6612 if (key != NULL) Push(key); 6705 if (key != NULL) Push(key);
6613 BuildLoad(expr, expr->LoadId()); 6706 BuildLoad(expr, expr->LoadId());
6614 } 6707 }
6615 6708
6616 6709
6617 static bool AreStringTypes(SmallMapList* types) {
6618 for (int i = 0; i < types->length(); i++) {
6619 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
6620 }
6621 return true;
6622 }
6623
6624
6625 void HOptimizedGraphBuilder::BuildLoad(Property* expr, 6710 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
6626 BailoutId ast_id) { 6711 BailoutId ast_id) {
6627 HInstruction* instr = NULL; 6712 HInstruction* instr = NULL;
6628 if (expr->IsStringAccess()) { 6713 if (expr->IsStringAccess()) {
6629 HValue* index = Pop(); 6714 HValue* index = Pop();
6630 HValue* string = Pop(); 6715 HValue* string = Pop();
6631 HInstruction* char_code = BuildStringCharCodeAt(string, index); 6716 HInstruction* char_code = BuildStringCharCodeAt(string, index);
6632 AddInstruction(char_code); 6717 AddInstruction(char_code);
6633 instr = NewUncasted<HStringCharFromCode>(char_code); 6718 instr = NewUncasted<HStringCharFromCode>(char_code);
6634 6719
6635 } else if (expr->IsFunctionPrototype()) { 6720 } else if (expr->IsFunctionPrototype()) {
6636 HValue* function = Pop(); 6721 HValue* function = Pop();
6637 BuildCheckHeapObject(function); 6722 BuildCheckHeapObject(function);
6638 instr = New<HLoadFunctionPrototype>(function); 6723 instr = New<HLoadFunctionPrototype>(function);
6639 6724
6640 } else if (expr->key()->IsPropertyName()) { 6725 } else if (expr->key()->IsPropertyName()) {
6641 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 6726 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
6642 HValue* object = Pop(); 6727 HValue* object = Pop();
6643 6728
6644 SmallMapList* types; 6729 instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
6645 ComputeReceiverTypes(expr, object, &types); 6730 object, name, NULL, expr->IsUninitialized());
6646 ASSERT(types != NULL); 6731 if (instr == NULL) return;
6647 6732 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
6648 if (types->length() > 0) {
6649 PropertyAccessInfo info(isolate(), types->first(), name);
6650 if (!info.CanLoadAsMonomorphic(types)) {
6651 return HandlePolymorphicLoadNamedField(
6652 ast_id, expr->LoadId(), object, types, name);
6653 }
6654
6655 BuildCheckHeapObject(object);
6656 HInstruction* checked_object;
6657 if (AreStringTypes(types)) {
6658 checked_object =
6659 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
6660 } else {
6661 checked_object = Add<HCheckMaps>(object, types);
6662 }
6663 instr = BuildLoadMonomorphic(
6664 &info, object, checked_object, ast_id, expr->LoadId());
6665 if (instr == NULL) return;
6666 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
6667 } else {
6668 instr = BuildLoadNamedGeneric(object, name, expr);
6669 }
6670 6733
6671 } else { 6734 } else {
6672 HValue* key = Pop(); 6735 HValue* key = Pop();
6673 HValue* obj = Pop(); 6736 HValue* obj = Pop();
6674 6737
6675 bool has_side_effects = false; 6738 bool has_side_effects = false;
6676 HValue* load = HandleKeyedElementAccess( 6739 HValue* load = HandleKeyedElementAccess(
6677 obj, key, NULL, expr, 6740 obj, key, NULL, expr, LOAD, &has_side_effects);
6678 false, // is_store
6679 &has_side_effects);
6680 if (has_side_effects) { 6741 if (has_side_effects) {
6681 if (ast_context()->IsEffect()) { 6742 if (ast_context()->IsEffect()) {
6682 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6743 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6683 } else { 6744 } else {
6684 Push(load); 6745 Push(load);
6685 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6746 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6686 Drop(1); 6747 Drop(1);
6687 } 6748 }
6688 } 6749 }
6689 return ast_context()->ReturnValue(load); 6750 return ast_context()->ReturnValue(load);
(...skipping 25 matching lines...) Expand all
6715 6776
6716 if (constant->map()->CanOmitMapChecks()) { 6777 if (constant->map()->CanOmitMapChecks()) {
6717 constant->map()->AddDependentCompilationInfo( 6778 constant->map()->AddDependentCompilationInfo(
6718 DependentCode::kPrototypeCheckGroup, info); 6779 DependentCode::kPrototypeCheckGroup, info);
6719 return constant_value; 6780 return constant_value;
6720 } 6781 }
6721 6782
6722 AddInstruction(constant_value); 6783 AddInstruction(constant_value);
6723 HCheckMaps* check = 6784 HCheckMaps* check =
6724 Add<HCheckMaps>(constant_value, handle(constant->map()), info); 6785 Add<HCheckMaps>(constant_value, handle(constant->map()), info);
6725 check->ClearGVNFlag(kDependsOnElementsKind); 6786 check->ClearDependsOnFlag(kElementsKind);
6726 return check; 6787 return check;
6727 } 6788 }
6728 6789
6729 6790
6730 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, 6791 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
6731 Handle<JSObject> holder) { 6792 Handle<JSObject> holder) {
6732 while (!prototype.is_identical_to(holder)) { 6793 while (!prototype.is_identical_to(holder)) {
6733 BuildConstantMapCheck(prototype, top_info()); 6794 BuildConstantMapCheck(prototype, top_info());
6734 prototype = handle(JSObject::cast(prototype->GetPrototype())); 6795 prototype = handle(JSObject::cast(prototype->GetPrototype()));
6735 } 6796 }
6736 6797
6737 HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info()); 6798 HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info());
6738 if (!checked_object->IsLinked()) AddInstruction(checked_object); 6799 if (!checked_object->IsLinked()) AddInstruction(checked_object);
6739 return checked_object; 6800 return checked_object;
6740 } 6801 }
6741 6802
6742 6803
6743 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, 6804 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
6744 Handle<Map> receiver_map) { 6805 Handle<Map> receiver_map) {
6745 if (!holder.is_null()) { 6806 if (!holder.is_null()) {
6746 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 6807 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
6747 BuildCheckPrototypeMaps(prototype, holder); 6808 BuildCheckPrototypeMaps(prototype, holder);
6748 } 6809 }
6749 } 6810 }
6750 6811
6751 6812
6752 void HOptimizedGraphBuilder::AddCheckConstantFunction(
6753 Handle<JSObject> holder,
6754 HValue* receiver,
6755 Handle<Map> receiver_map) {
6756 // Constant functions have the nice property that the map will change if they
6757 // are overwritten. Therefore it is enough to check the map of the holder and
6758 // its prototypes.
6759 AddCheckMap(receiver, receiver_map);
6760 AddCheckPrototypeMaps(holder, receiver_map);
6761 }
6762
6763
6764 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall( 6813 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
6765 HValue* fun, int argument_count, bool pass_argument_count) { 6814 HValue* fun, int argument_count, bool pass_argument_count) {
6766 return New<HCallJSFunction>( 6815 return New<HCallJSFunction>(
6767 fun, argument_count, pass_argument_count); 6816 fun, argument_count, pass_argument_count);
6768 } 6817 }
6769 6818
6770 6819
6771 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall( 6820 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
6772 HValue* fun, HValue* context, 6821 HValue* fun, HValue* context,
6773 int argument_count, HValue* expected_param_count) { 6822 int argument_count, HValue* expected_param_count) {
(...skipping 20 matching lines...) Expand all
6794 // For constant functions, we try to avoid calling the 6843 // For constant functions, we try to avoid calling the
6795 // argument adaptor and instead call the function directly 6844 // argument adaptor and instead call the function directly
6796 int formal_parameter_count = jsfun->shared()->formal_parameter_count(); 6845 int formal_parameter_count = jsfun->shared()->formal_parameter_count();
6797 bool dont_adapt_arguments = 6846 bool dont_adapt_arguments =
6798 (formal_parameter_count == 6847 (formal_parameter_count ==
6799 SharedFunctionInfo::kDontAdaptArgumentsSentinel); 6848 SharedFunctionInfo::kDontAdaptArgumentsSentinel);
6800 int arity = argument_count - 1; 6849 int arity = argument_count - 1;
6801 bool can_invoke_directly = 6850 bool can_invoke_directly =
6802 dont_adapt_arguments || formal_parameter_count == arity; 6851 dont_adapt_arguments || formal_parameter_count == arity;
6803 if (can_invoke_directly) { 6852 if (can_invoke_directly) {
6853 if (jsfun.is_identical_to(current_info()->closure())) {
6854 graph()->MarkRecursive();
6855 }
6804 return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments); 6856 return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
6805 } else { 6857 } else {
6806 HValue* param_count_value = Add<HConstant>(formal_parameter_count); 6858 HValue* param_count_value = Add<HConstant>(formal_parameter_count);
6807 HValue* context = Add<HLoadNamedField>(target, 6859 HValue* context = Add<HLoadNamedField>(
6860 target, static_cast<HValue*>(NULL),
6808 HObjectAccess::ForFunctionContextPointer()); 6861 HObjectAccess::ForFunctionContextPointer());
6809 return NewArgumentAdaptorCall(target, context, 6862 return NewArgumentAdaptorCall(target, context,
6810 argument_count, param_count_value); 6863 argument_count, param_count_value);
6811 } 6864 }
6812 UNREACHABLE(); 6865 UNREACHABLE();
6813 return NULL; 6866 return NULL;
6814 } 6867 }
6815 6868
6816 6869
6817 HInstruction* HOptimizedGraphBuilder::NewCallNamed(
6818 Handle<String> name, int argument_count) {
6819 CallInterfaceDescriptor* descriptor =
6820 isolate()->call_descriptor(Isolate::NamedCall);
6821 HValue* op_vals[] = { context(), Add<HConstant>(name) };
6822 int arity = argument_count - 1;
6823 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity);
6824
6825 return New<HCallWithDescriptor>(
6826 Add<HConstant>(ic), argument_count, descriptor,
6827 Vector<HValue*>(op_vals, descriptor->environment_length()));
6828 }
6829
6830
6831 HInstruction* HOptimizedGraphBuilder::NewCallKeyed(
6832 HValue* key, int argument_count) {
6833 CallInterfaceDescriptor* descriptor =
6834 isolate()->call_descriptor(Isolate::KeyedCall);
6835 HValue* op_vals[] = { context(), key };
6836 int arity = argument_count - 1;
6837 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
6838
6839 return New<HCallWithDescriptor>(
6840 Add<HConstant>(ic), argument_count, descriptor,
6841 Vector<HValue*>(op_vals, descriptor->environment_length()));
6842 }
6843
6844 class FunctionSorter {
6845 public:
6846 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { }
6847 FunctionSorter(int index, int ticks, int ast_length, int src_length)
6848 : index_(index),
6849 ticks_(ticks),
6850 ast_length_(ast_length),
6851 src_length_(src_length) { }
6852
6853 int index() const { return index_; }
6854 int ticks() const { return ticks_; }
6855 int ast_length() const { return ast_length_; }
6856 int src_length() const { return src_length_; }
6857
6858 private:
6859 int index_;
6860 int ticks_;
6861 int ast_length_;
6862 int src_length_;
6863 };
6864
6865
6866 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
6867 int diff = lhs.ticks() - rhs.ticks();
6868 if (diff != 0) return diff > 0;
6869 diff = lhs.ast_length() - rhs.ast_length();
6870 if (diff != 0) return diff < 0;
6871 return lhs.src_length() < rhs.src_length();
6872 }
6873
6874
6875 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
6876 Call* expr,
6877 HValue* receiver,
6878 SmallMapList* types,
6879 Handle<String> name) {
6880 if (types->length() > kMaxCallPolymorphism) return false;
6881
6882 PropertyAccessInfo info(isolate(), types->at(0), name);
6883 if (!info.CanLoadAsMonomorphic(types)) return false;
6884 if (!expr->ComputeTarget(info.map(), name)) return false;
6885
6886 BuildCheckHeapObject(receiver);
6887 Add<HCheckMaps>(receiver, types);
6888 AddCheckPrototypeMaps(expr->holder(), info.map());
6889 if (FLAG_trace_inlining) {
6890 Handle<JSFunction> caller = current_info()->closure();
6891 SmartArrayPointer<char> caller_name =
6892 caller->shared()->DebugName()->ToCString();
6893 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6894 name->ToCString().get(), caller_name.get());
6895 }
6896
6897 if (!TryInlineCall(expr)) {
6898 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6899 HInstruction* call = BuildCallConstantFunction(
6900 expr->target(), argument_count);
6901 PushArgumentsFromEnvironment(argument_count);
6902 AddInstruction(call);
6903 if (!ast_context()->IsEffect()) Push(call);
6904 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
6905 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6906 }
6907
6908 return true;
6909 }
6910
6911
6912 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( 6870 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
6913 Call* expr, 6871 Call* expr,
6914 HValue* receiver, 6872 HValue* receiver,
6915 SmallMapList* types, 6873 SmallMapList* types,
6916 Handle<String> name) { 6874 Handle<String> name) {
6917 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
6918
6919 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6875 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6920 HBasicBlock* join = NULL; 6876 int order[kMaxCallPolymorphism];
6921 FunctionSorter order[kMaxCallPolymorphism];
6922 int ordered_functions = 0;
6923
6924 Handle<Map> initial_string_map(
6925 isolate()->native_context()->string_function()->initial_map());
6926 Handle<Map> string_marker_map(
6927 JSObject::cast(initial_string_map->prototype())->map());
6928 Handle<Map> initial_number_map(
6929 isolate()->native_context()->number_function()->initial_map());
6930 Handle<Map> number_marker_map(
6931 JSObject::cast(initial_number_map->prototype())->map());
6932 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6933 6877
6934 bool handle_smi = false; 6878 bool handle_smi = false;
6879 bool handled_string = false;
6880 int ordered_functions = 0;
6935 6881
6936 for (int i = 0; 6882 for (int i = 0;
6937 i < types->length() && ordered_functions < kMaxCallPolymorphism; 6883 i < types->length() && ordered_functions < kMaxCallPolymorphism;
6938 ++i) { 6884 ++i) {
6939 Handle<Map> map = types->at(i); 6885 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
6940 if (expr->ComputeTarget(map, name)) { 6886 if (info.CanAccessMonomorphic() &&
6941 if (map.is_identical_to(number_marker_map)) handle_smi = true; 6887 info.lookup()->IsConstant() &&
6942 order[ordered_functions++] = 6888 info.constant()->IsJSFunction()) {
6943 FunctionSorter(i, 6889 if (info.type()->Is(Type::String())) {
6944 expr->target()->shared()->profiler_ticks(), 6890 if (handled_string) continue;
6945 InliningAstSize(expr->target()), 6891 handled_string = true;
6946 expr->target()->shared()->SourceSize()); 6892 }
6893 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
6894 if (info.type()->Is(Type::Number())) {
6895 handle_smi = true;
6896 }
6897 expr->set_target(target);
6898 order[ordered_functions++] = i;
6947 } 6899 }
6948 } 6900 }
6949 6901
6950 std::sort(order, order + ordered_functions);
6951
6952 HBasicBlock* number_block = NULL; 6902 HBasicBlock* number_block = NULL;
6903 HBasicBlock* join = NULL;
6904 handled_string = false;
6905 int count = 0;
6953 6906
6954 for (int fn = 0; fn < ordered_functions; ++fn) { 6907 for (int fn = 0; fn < ordered_functions; ++fn) {
6955 int i = order[fn].index(); 6908 int i = order[fn];
6956 Handle<Map> map = types->at(i); 6909 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
6957 if (fn == 0) { 6910 if (info.type()->Is(Type::String())) {
6911 if (handled_string) continue;
6912 handled_string = true;
6913 }
6914 // Reloads the target.
6915 info.CanAccessMonomorphic();
6916 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
6917
6918 expr->set_target(target);
6919 if (count == 0) {
6958 // Only needed once. 6920 // Only needed once.
6959 join = graph()->CreateBasicBlock(); 6921 join = graph()->CreateBasicBlock();
6960 if (handle_smi) { 6922 if (handle_smi) {
6961 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 6923 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6962 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 6924 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6963 number_block = graph()->CreateBasicBlock(); 6925 number_block = graph()->CreateBasicBlock();
6964 FinishCurrentBlock(New<HIsSmiAndBranch>( 6926 FinishCurrentBlock(New<HIsSmiAndBranch>(
6965 receiver, empty_smi_block, not_smi_block)); 6927 receiver, empty_smi_block, not_smi_block));
6966 Goto(empty_smi_block, number_block); 6928 GotoNoSimulate(empty_smi_block, number_block);
6967 set_current_block(not_smi_block); 6929 set_current_block(not_smi_block);
6968 } else { 6930 } else {
6969 BuildCheckHeapObject(receiver); 6931 BuildCheckHeapObject(receiver);
6970 } 6932 }
6971 } 6933 }
6934 ++count;
6972 HBasicBlock* if_true = graph()->CreateBasicBlock(); 6935 HBasicBlock* if_true = graph()->CreateBasicBlock();
6973 HBasicBlock* if_false = graph()->CreateBasicBlock(); 6936 HBasicBlock* if_false = graph()->CreateBasicBlock();
6974 HUnaryControlInstruction* compare; 6937 HUnaryControlInstruction* compare;
6975 6938
6976 if (handle_smi && map.is_identical_to(number_marker_map)) { 6939 Handle<Map> map = info.map();
6940 if (info.type()->Is(Type::Number())) {
6941 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6977 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); 6942 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
6978 map = initial_number_map; 6943 } else if (info.type()->Is(Type::String())) {
6979 expr->set_number_check(
6980 Handle<JSObject>(JSObject::cast(map->prototype())));
6981 } else if (map.is_identical_to(string_marker_map)) {
6982 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); 6944 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
6983 map = initial_string_map;
6984 expr->set_string_check(
6985 Handle<JSObject>(JSObject::cast(map->prototype())));
6986 } else { 6945 } else {
6987 compare = New<HCompareMap>(receiver, map, if_true, if_false); 6946 compare = New<HCompareMap>(receiver, map, if_true, if_false);
6988 expr->set_map_check(); 6947 }
6948 FinishCurrentBlock(compare);
6949
6950 if (info.type()->Is(Type::Number())) {
6951 GotoNoSimulate(if_true, number_block);
6952 if_true = number_block;
6989 } 6953 }
6990 6954
6991 FinishCurrentBlock(compare);
6992
6993 if (expr->check_type() == NUMBER_CHECK) {
6994 Goto(if_true, number_block);
6995 if_true = number_block;
6996 number_block->SetJoinId(expr->id());
6997 }
6998 set_current_block(if_true); 6955 set_current_block(if_true);
6999 6956
7000 expr->ComputeTarget(map, name); 6957 AddCheckPrototypeMaps(info.holder(), map);
7001 AddCheckPrototypeMaps(expr->holder(), map); 6958
7002 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 6959 HValue* function = Add<HConstant>(expr->target());
6960 environment()->SetExpressionStackAt(0, function);
6961 Push(receiver);
6962 CHECK_ALIVE(VisitExpressions(expr->arguments()));
6963 bool needs_wrapping = NeedsWrappingFor(info.type(), target);
6964 bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
6965 if (FLAG_trace_inlining && try_inline) {
7003 Handle<JSFunction> caller = current_info()->closure(); 6966 Handle<JSFunction> caller = current_info()->closure();
7004 SmartArrayPointer<char> caller_name = 6967 SmartArrayPointer<char> caller_name =
7005 caller->shared()->DebugName()->ToCString(); 6968 caller->shared()->DebugName()->ToCString();
7006 PrintF("Trying to inline the polymorphic call to %s from %s\n", 6969 PrintF("Trying to inline the polymorphic call to %s from %s\n",
7007 name->ToCString().get(), 6970 name->ToCString().get(),
7008 caller_name.get()); 6971 caller_name.get());
7009 } 6972 }
7010 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { 6973 if (try_inline && TryInlineCall(expr)) {
7011 // Trying to inline will signal that we should bailout from the 6974 // Trying to inline will signal that we should bailout from the
7012 // entire compilation by setting stack overflow on the visitor. 6975 // entire compilation by setting stack overflow on the visitor.
7013 if (HasStackOverflow()) return; 6976 if (HasStackOverflow()) return;
7014 } else { 6977 } else {
7015 HInstruction* call = BuildCallConstantFunction( 6978 // Since HWrapReceiver currently cannot actually wrap numbers and strings,
7016 expr->target(), argument_count); 6979 // use the regular CallFunctionStub for method calls to wrap the receiver.
6980 // TODO(verwaest): Support creation of value wrappers directly in
6981 // HWrapReceiver.
6982 HInstruction* call = needs_wrapping
6983 ? NewUncasted<HCallFunction>(
6984 function, argument_count, WRAP_AND_CALL)
6985 : BuildCallConstantFunction(target, argument_count);
7017 PushArgumentsFromEnvironment(argument_count); 6986 PushArgumentsFromEnvironment(argument_count);
7018 AddInstruction(call); 6987 AddInstruction(call);
6988 Drop(1); // Drop the function.
7019 if (!ast_context()->IsEffect()) Push(call); 6989 if (!ast_context()->IsEffect()) Push(call);
7020 } 6990 }
7021 6991
7022 if (current_block() != NULL) Goto(join); 6992 if (current_block() != NULL) Goto(join);
7023 set_current_block(if_false); 6993 set_current_block(if_false);
7024 } 6994 }
7025 6995
7026 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6996 // Finish up. Unconditionally deoptimize if we've handled all the maps we
7027 // know about and do not want to handle ones we've never seen. Otherwise 6997 // know about and do not want to handle ones we've never seen. Otherwise
7028 // use a generic IC. 6998 // use a generic IC.
7029 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 6999 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
7030 // Because the deopt may be the only path in the polymorphic call, make sure 7000 FinishExitWithHardDeoptimization("Unknown map in polymorphic call");
7031 // that the environment stack matches the depth on deopt that it otherwise
7032 // would have had after a successful call.
7033 Drop(argument_count);
7034 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
7035 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
7036 } else { 7001 } else {
7037 HInstruction* call = NewCallNamed(name, argument_count); 7002 Property* prop = expr->expression()->AsProperty();
7003 HInstruction* function = BuildNamedGeneric(
7004 LOAD, receiver, name, NULL, prop->IsUninitialized());
7005 AddInstruction(function);
7006 Push(function);
7007 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
7008
7009 environment()->SetExpressionStackAt(1, function);
7010 environment()->SetExpressionStackAt(0, receiver);
7011 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7012
7013 CallFunctionFlags flags = receiver->type().IsJSObject()
7014 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
7015 HInstruction* call = New<HCallFunction>(
7016 function, argument_count, flags);
7017
7038 PushArgumentsFromEnvironment(argument_count); 7018 PushArgumentsFromEnvironment(argument_count);
7039 7019
7020 Drop(1); // Function.
7021
7040 if (join != NULL) { 7022 if (join != NULL) {
7041 AddInstruction(call); 7023 AddInstruction(call);
7042 if (!ast_context()->IsEffect()) Push(call); 7024 if (!ast_context()->IsEffect()) Push(call);
7043 Goto(join); 7025 Goto(join);
7044 } else { 7026 } else {
7045 return ast_context()->ReturnInstruction(call, expr->id()); 7027 return ast_context()->ReturnInstruction(call, expr->id());
7046 } 7028 }
7047 } 7029 }
7048 7030
7049 // We assume that control flow is always live after an expression. So 7031 // We assume that control flow is always live after an expression. So
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
7116 int nodes_added = target_shared->ast_node_count(); 7098 int nodes_added = target_shared->ast_node_count();
7117 return nodes_added; 7099 return nodes_added;
7118 } 7100 }
7119 7101
7120 7102
7121 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, 7103 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
7122 int arguments_count, 7104 int arguments_count,
7123 HValue* implicit_return_value, 7105 HValue* implicit_return_value,
7124 BailoutId ast_id, 7106 BailoutId ast_id,
7125 BailoutId return_id, 7107 BailoutId return_id,
7126 InliningKind inlining_kind) { 7108 InliningKind inlining_kind,
7109 HSourcePosition position) {
7127 int nodes_added = InliningAstSize(target); 7110 int nodes_added = InliningAstSize(target);
7128 if (nodes_added == kNotInlinable) return false; 7111 if (nodes_added == kNotInlinable) return false;
7129 7112
7130 Handle<JSFunction> caller = current_info()->closure(); 7113 Handle<JSFunction> caller = current_info()->closure();
7131 7114
7132 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 7115 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7133 TraceInline(target, caller, "target AST is too large [early]"); 7116 TraceInline(target, caller, "target AST is too large [early]");
7134 return false; 7117 return false;
7135 } 7118 }
7136 7119
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
7248 } 7231 }
7249 7232
7250 // ---------------------------------------------------------------- 7233 // ----------------------------------------------------------------
7251 // After this point, we've made a decision to inline this function (so 7234 // After this point, we've made a decision to inline this function (so
7252 // TryInline should always return true). 7235 // TryInline should always return true).
7253 7236
7254 // Type-check the inlined function. 7237 // Type-check the inlined function.
7255 ASSERT(target_shared->has_deoptimization_support()); 7238 ASSERT(target_shared->has_deoptimization_support());
7256 AstTyper::Run(&target_info); 7239 AstTyper::Run(&target_info);
7257 7240
7241 int function_id = graph()->TraceInlinedFunction(target_shared, position);
7242
7258 // Save the pending call context. Set up new one for the inlined function. 7243 // Save the pending call context. Set up new one for the inlined function.
7259 // The function state is new-allocated because we need to delete it 7244 // The function state is new-allocated because we need to delete it
7260 // in two different places. 7245 // in two different places.
7261 FunctionState* target_state = new FunctionState( 7246 FunctionState* target_state = new FunctionState(
7262 this, &target_info, inlining_kind); 7247 this, &target_info, inlining_kind, function_id);
7263 7248
7264 HConstant* undefined = graph()->GetConstantUndefined(); 7249 HConstant* undefined = graph()->GetConstantUndefined();
7265 7250
7266 HEnvironment* inner_env = 7251 HEnvironment* inner_env =
7267 environment()->CopyForInlining(target, 7252 environment()->CopyForInlining(target,
7268 arguments_count, 7253 arguments_count,
7269 function, 7254 function,
7270 undefined, 7255 undefined,
7271 function_state()->inlining_kind()); 7256 function_state()->inlining_kind());
7272 7257
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
7393 function_return()->SetJoinId(ast_id); 7378 function_return()->SetJoinId(ast_id);
7394 set_current_block(function_return()); 7379 set_current_block(function_return());
7395 } else { 7380 } else {
7396 set_current_block(NULL); 7381 set_current_block(NULL);
7397 } 7382 }
7398 delete target_state; 7383 delete target_state;
7399 return true; 7384 return true;
7400 } 7385 }
7401 7386
7402 7387
7403 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { 7388 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
7404 return TryInline(expr->target(), 7389 return TryInline(expr->target(),
7405 expr->arguments()->length(), 7390 expr->arguments()->length(),
7406 NULL, 7391 NULL,
7407 expr->id(), 7392 expr->id(),
7408 expr->ReturnId(), 7393 expr->ReturnId(),
7409 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); 7394 NORMAL_RETURN,
7395 ScriptPositionToSourcePosition(expr->position()));
7410 } 7396 }
7411 7397
7412 7398
7413 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, 7399 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
7414 HValue* implicit_return_value) { 7400 HValue* implicit_return_value) {
7415 return TryInline(expr->target(), 7401 return TryInline(expr->target(),
7416 expr->arguments()->length(), 7402 expr->arguments()->length(),
7417 implicit_return_value, 7403 implicit_return_value,
7418 expr->id(), 7404 expr->id(),
7419 expr->ReturnId(), 7405 expr->ReturnId(),
7420 CONSTRUCT_CALL_RETURN); 7406 CONSTRUCT_CALL_RETURN,
7407 ScriptPositionToSourcePosition(expr->position()));
7421 } 7408 }
7422 7409
7423 7410
7424 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, 7411 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
7412 Handle<Map> receiver_map,
7425 BailoutId ast_id, 7413 BailoutId ast_id,
7426 BailoutId return_id) { 7414 BailoutId return_id) {
7415 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
7427 return TryInline(getter, 7416 return TryInline(getter,
7428 0, 7417 0,
7429 NULL, 7418 NULL,
7430 ast_id, 7419 ast_id,
7431 return_id, 7420 return_id,
7432 GETTER_CALL_RETURN); 7421 GETTER_CALL_RETURN,
7422 source_position());
7433 } 7423 }
7434 7424
7435 7425
7436 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, 7426 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
7427 Handle<Map> receiver_map,
7437 BailoutId id, 7428 BailoutId id,
7438 BailoutId assignment_id, 7429 BailoutId assignment_id,
7439 HValue* implicit_return_value) { 7430 HValue* implicit_return_value) {
7431 if (TryInlineApiSetter(setter, receiver_map, id)) return true;
7440 return TryInline(setter, 7432 return TryInline(setter,
7441 1, 7433 1,
7442 implicit_return_value, 7434 implicit_return_value,
7443 id, assignment_id, 7435 id, assignment_id,
7444 SETTER_CALL_RETURN); 7436 SETTER_CALL_RETURN,
7437 source_position());
7445 } 7438 }
7446 7439
7447 7440
7448 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, 7441 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
7449 Call* expr, 7442 Call* expr,
7450 int arguments_count) { 7443 int arguments_count) {
7451 return TryInline(function, 7444 return TryInline(function,
7452 arguments_count, 7445 arguments_count,
7453 NULL, 7446 NULL,
7454 expr->id(), 7447 expr->id(),
7455 expr->ReturnId(), 7448 expr->ReturnId(),
7456 NORMAL_RETURN); 7449 NORMAL_RETURN,
7450 ScriptPositionToSourcePosition(expr->position()));
7457 } 7451 }
7458 7452
7459 7453
7460 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, 7454 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
7461 bool drop_extra) {
7462 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 7455 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
7463 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7456 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7464 switch (id) { 7457 switch (id) {
7465 case kMathExp: 7458 case kMathExp:
7466 if (!FLAG_fast_math) break; 7459 if (!FLAG_fast_math) break;
7467 // Fall through if FLAG_fast_math. 7460 // Fall through if FLAG_fast_math.
7468 case kMathRound: 7461 case kMathRound:
7469 case kMathFloor: 7462 case kMathFloor:
7470 case kMathAbs: 7463 case kMathAbs:
7471 case kMathSqrt: 7464 case kMathSqrt:
7472 case kMathLog: 7465 case kMathLog:
7466 case kMathClz32:
7473 if (expr->arguments()->length() == 1) { 7467 if (expr->arguments()->length() == 1) {
7474 HValue* argument = Pop(); 7468 HValue* argument = Pop();
7475 Drop(1); // Receiver. 7469 Drop(2); // Receiver and function.
7476 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7470 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7477 if (drop_extra) Drop(1); // Optionally drop the function.
7478 ast_context()->ReturnInstruction(op, expr->id()); 7471 ast_context()->ReturnInstruction(op, expr->id());
7479 return true; 7472 return true;
7480 } 7473 }
7481 break; 7474 break;
7482 case kMathImul: 7475 case kMathImul:
7483 if (expr->arguments()->length() == 2) { 7476 if (expr->arguments()->length() == 2) {
7484 HValue* right = Pop(); 7477 HValue* right = Pop();
7485 HValue* left = Pop(); 7478 HValue* left = Pop();
7486 Drop(1); // Receiver. 7479 Drop(2); // Receiver and function.
7487 HInstruction* op = HMul::NewImul(zone(), context(), left, right); 7480 HInstruction* op = HMul::NewImul(zone(), context(), left, right);
7488 if (drop_extra) Drop(1); // Optionally drop the function.
7489 ast_context()->ReturnInstruction(op, expr->id()); 7481 ast_context()->ReturnInstruction(op, expr->id());
7490 return true; 7482 return true;
7491 } 7483 }
7492 break; 7484 break;
7493 default: 7485 default:
7494 // Not supported for inlining yet. 7486 // Not supported for inlining yet.
7495 break; 7487 break;
7496 } 7488 }
7497 return false; 7489 return false;
7498 } 7490 }
7499 7491
7500 7492
7501 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( 7493 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
7502 Call* expr, 7494 Call* expr,
7503 HValue* receiver, 7495 HValue* receiver,
7504 Handle<Map> receiver_map, 7496 Handle<Map> receiver_map) {
7505 CheckType check_type) {
7506 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
7507 // Try to inline calls like Math.* as operations in the calling function. 7497 // Try to inline calls like Math.* as operations in the calling function.
7508 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 7498 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
7509 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7499 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7510 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 7500 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7511 switch (id) { 7501 switch (id) {
7512 case kStringCharCodeAt: 7502 case kStringCharCodeAt:
7513 case kStringCharAt: 7503 case kStringCharAt:
7514 if (argument_count == 2 && check_type == STRING_CHECK) { 7504 if (argument_count == 2) {
7515 HValue* index = Pop(); 7505 HValue* index = Pop();
7516 HValue* string = Pop(); 7506 HValue* string = Pop();
7517 ASSERT(!expr->holder().is_null()); 7507 Drop(1); // Function.
7518 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
7519 STRING_CHECK, expr->holder()->GetIsolate()),
7520 expr->holder());
7521 HInstruction* char_code = 7508 HInstruction* char_code =
7522 BuildStringCharCodeAt(string, index); 7509 BuildStringCharCodeAt(string, index);
7523 if (id == kStringCharCodeAt) { 7510 if (id == kStringCharCodeAt) {
7524 ast_context()->ReturnInstruction(char_code, expr->id()); 7511 ast_context()->ReturnInstruction(char_code, expr->id());
7525 return true; 7512 return true;
7526 } 7513 }
7527 AddInstruction(char_code); 7514 AddInstruction(char_code);
7528 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); 7515 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
7529 ast_context()->ReturnInstruction(result, expr->id()); 7516 ast_context()->ReturnInstruction(result, expr->id());
7530 return true; 7517 return true;
7531 } 7518 }
7532 break; 7519 break;
7533 case kStringFromCharCode: 7520 case kStringFromCharCode:
7534 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 7521 if (argument_count == 2) {
7535 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7536 HValue* argument = Pop(); 7522 HValue* argument = Pop();
7537 Drop(1); // Receiver. 7523 Drop(2); // Receiver and function.
7538 HInstruction* result = NewUncasted<HStringCharFromCode>(argument); 7524 HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
7539 ast_context()->ReturnInstruction(result, expr->id()); 7525 ast_context()->ReturnInstruction(result, expr->id());
7540 return true; 7526 return true;
7541 } 7527 }
7542 break; 7528 break;
7543 case kMathExp: 7529 case kMathExp:
7544 if (!FLAG_fast_math) break; 7530 if (!FLAG_fast_math) break;
7545 // Fall through if FLAG_fast_math. 7531 // Fall through if FLAG_fast_math.
7546 case kMathRound: 7532 case kMathRound:
7547 case kMathFloor: 7533 case kMathFloor:
7548 case kMathAbs: 7534 case kMathAbs:
7549 case kMathSqrt: 7535 case kMathSqrt:
7550 case kMathLog: 7536 case kMathLog:
7551 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 7537 case kMathClz32:
7552 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 7538 if (argument_count == 2) {
7553 HValue* argument = Pop(); 7539 HValue* argument = Pop();
7554 Drop(1); // Receiver. 7540 Drop(2); // Receiver and function.
7555 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7541 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7556 ast_context()->ReturnInstruction(op, expr->id()); 7542 ast_context()->ReturnInstruction(op, expr->id());
7557 return true; 7543 return true;
7558 } 7544 }
7559 break; 7545 break;
7560 case kMathPow: 7546 case kMathPow:
7561 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7547 if (argument_count == 3) {
7562 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7563 HValue* right = Pop(); 7548 HValue* right = Pop();
7564 HValue* left = Pop(); 7549 HValue* left = Pop();
7565 Pop(); // Pop receiver. 7550 Drop(2); // Receiver and function.
7566 HInstruction* result = NULL; 7551 HInstruction* result = NULL;
7567 // Use sqrt() if exponent is 0.5 or -0.5. 7552 // Use sqrt() if exponent is 0.5 or -0.5.
7568 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 7553 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
7569 double exponent = HConstant::cast(right)->DoubleValue(); 7554 double exponent = HConstant::cast(right)->DoubleValue();
7570 if (exponent == 0.5) { 7555 if (exponent == 0.5) {
7571 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf); 7556 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
7572 } else if (exponent == -0.5) { 7557 } else if (exponent == -0.5) {
7573 HValue* one = graph()->GetConstant1(); 7558 HValue* one = graph()->GetConstant1();
7574 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>( 7559 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
7575 left, kMathPowHalf); 7560 left, kMathPowHalf);
7576 // MathPowHalf doesn't have side effects so there's no need for 7561 // MathPowHalf doesn't have side effects so there's no need for
7577 // an environment simulation here. 7562 // an environment simulation here.
7578 ASSERT(!sqrt->HasObservableSideEffects()); 7563 ASSERT(!sqrt->HasObservableSideEffects());
7579 result = NewUncasted<HDiv>(one, sqrt); 7564 result = NewUncasted<HDiv>(one, sqrt);
7580 } else if (exponent == 2.0) { 7565 } else if (exponent == 2.0) {
7581 result = NewUncasted<HMul>(left, left); 7566 result = NewUncasted<HMul>(left, left);
7582 } 7567 }
7583 } 7568 }
7584 7569
7585 if (result == NULL) { 7570 if (result == NULL) {
7586 result = NewUncasted<HPower>(left, right); 7571 result = NewUncasted<HPower>(left, right);
7587 } 7572 }
7588 ast_context()->ReturnInstruction(result, expr->id()); 7573 ast_context()->ReturnInstruction(result, expr->id());
7589 return true; 7574 return true;
7590 } 7575 }
7591 break; 7576 break;
7592 case kMathMax: 7577 case kMathMax:
7593 case kMathMin: 7578 case kMathMin:
7594 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7579 if (argument_count == 3) {
7595 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7596 HValue* right = Pop(); 7580 HValue* right = Pop();
7597 HValue* left = Pop(); 7581 HValue* left = Pop();
7598 Drop(1); // Receiver. 7582 Drop(2); // Receiver and function.
7599 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin 7583 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
7600 : HMathMinMax::kMathMax; 7584 : HMathMinMax::kMathMax;
7601 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); 7585 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
7602 ast_context()->ReturnInstruction(result, expr->id()); 7586 ast_context()->ReturnInstruction(result, expr->id());
7603 return true; 7587 return true;
7604 } 7588 }
7605 break; 7589 break;
7606 case kMathImul: 7590 case kMathImul:
7607 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7591 if (argument_count == 3) {
7608 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7609 HValue* right = Pop(); 7592 HValue* right = Pop();
7610 HValue* left = Pop(); 7593 HValue* left = Pop();
7611 Drop(1); // Receiver. 7594 Drop(2); // Receiver and function.
7612 HInstruction* result = HMul::NewImul(zone(), context(), left, right); 7595 HInstruction* result = HMul::NewImul(zone(), context(), left, right);
7613 ast_context()->ReturnInstruction(result, expr->id()); 7596 ast_context()->ReturnInstruction(result, expr->id());
7614 return true; 7597 return true;
7615 } 7598 }
7616 break; 7599 break;
7600 case kArrayPop: {
7601 if (receiver_map.is_null()) return false;
7602 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
7603 ElementsKind elements_kind = receiver_map->elements_kind();
7604 if (!IsFastElementsKind(elements_kind)) return false;
7605
7606 Drop(expr->arguments()->length());
7607 HValue* result;
7608 HValue* reduced_length;
7609 HValue* receiver = Pop();
7610
7611 HValue* checked_object = AddCheckMap(receiver, receiver_map);
7612 HValue* length = Add<HLoadNamedField>(
7613 checked_object, static_cast<HValue*>(NULL),
7614 HObjectAccess::ForArrayLength(elements_kind));
7615
7616 Drop(1); // Function.
7617
7618 { NoObservableSideEffectsScope scope(this);
7619 IfBuilder length_checker(this);
7620
7621 HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
7622 length, graph()->GetConstant0(), Token::EQ);
7623 length_checker.Then();
7624
7625 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
7626
7627 length_checker.Else();
7628 HValue* elements = AddLoadElements(checked_object);
7629 // Ensure that we aren't popping from a copy-on-write array.
7630 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
7631 elements = BuildCopyElementsOnWrite(checked_object, elements,
7632 elements_kind, length);
7633 }
7634 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
7635 result = AddElementAccess(elements, reduced_length, NULL,
7636 bounds_check, elements_kind, LOAD);
7637 Factory* factory = isolate()->factory();
7638 double nan_double = FixedDoubleArray::hole_nan_as_double();
7639 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
7640 ? Add<HConstant>(factory->the_hole_value())
7641 : Add<HConstant>(nan_double);
7642 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
7643 elements_kind = FAST_HOLEY_ELEMENTS;
7644 }
7645 AddElementAccess(
7646 elements, reduced_length, hole, bounds_check, elements_kind, STORE);
7647 Add<HStoreNamedField>(
7648 checked_object, HObjectAccess::ForArrayLength(elements_kind),
7649 reduced_length, STORE_TO_INITIALIZED_ENTRY);
7650
7651 if (!ast_context()->IsEffect()) Push(result);
7652
7653 length_checker.End();
7654 }
7655 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
7656 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
7657 if (!ast_context()->IsEffect()) Drop(1);
7658
7659 ast_context()->ReturnValue(result);
7660 return true;
7661 }
7662 case kArrayPush: {
7663 if (receiver_map.is_null()) return false;
7664 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
7665 ElementsKind elements_kind = receiver_map->elements_kind();
7666 if (!IsFastElementsKind(elements_kind)) return false;
7667
7668 HValue* op_vals[] = {
7669 context(),
7670 // Receiver.
7671 environment()->ExpressionStackAt(expr->arguments()->length())
7672 };
7673
7674 const int argc = expr->arguments()->length();
7675 // Includes receiver.
7676 PushArgumentsFromEnvironment(argc + 1);
7677
7678 CallInterfaceDescriptor* descriptor =
7679 isolate()->call_descriptor(Isolate::CallHandler);
7680
7681 ArrayPushStub stub(receiver_map->elements_kind(), argc);
7682 Handle<Code> code = stub.GetCode(isolate());
7683 HConstant* code_value = Add<HConstant>(code);
7684
7685 ASSERT((sizeof(op_vals) / kPointerSize) ==
7686 descriptor->environment_length());
7687
7688 HInstruction* call = New<HCallWithDescriptor>(
7689 code_value, argc + 1, descriptor,
7690 Vector<HValue*>(op_vals, descriptor->environment_length()));
7691 Drop(1); // Drop function.
7692 ast_context()->ReturnInstruction(call, expr->id());
7693 return true;
7694 }
7617 default: 7695 default:
7618 // Not yet supported for inlining. 7696 // Not yet supported for inlining.
7619 break; 7697 break;
7620 } 7698 }
7621 return false; 7699 return false;
7622 } 7700 }
7623 7701
7624 7702
7703 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
7704 HValue* receiver) {
7705 Handle<JSFunction> function = expr->target();
7706 int argc = expr->arguments()->length();
7707 SmallMapList receiver_maps;
7708 return TryInlineApiCall(function,
7709 receiver,
7710 &receiver_maps,
7711 argc,
7712 expr->id(),
7713 kCallApiFunction);
7714 }
7715
7716
7717 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
7718 Call* expr,
7719 HValue* receiver,
7720 SmallMapList* receiver_maps) {
7721 Handle<JSFunction> function = expr->target();
7722 int argc = expr->arguments()->length();
7723 return TryInlineApiCall(function,
7724 receiver,
7725 receiver_maps,
7726 argc,
7727 expr->id(),
7728 kCallApiMethod);
7729 }
7730
7731
7732 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
7733 Handle<Map> receiver_map,
7734 BailoutId ast_id) {
7735 SmallMapList receiver_maps(1, zone());
7736 receiver_maps.Add(receiver_map, zone());
7737 return TryInlineApiCall(function,
7738 NULL, // Receiver is on expression stack.
7739 &receiver_maps,
7740 0,
7741 ast_id,
7742 kCallApiGetter);
7743 }
7744
7745
7746 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
7747 Handle<Map> receiver_map,
7748 BailoutId ast_id) {
7749 SmallMapList receiver_maps(1, zone());
7750 receiver_maps.Add(receiver_map, zone());
7751 return TryInlineApiCall(function,
7752 NULL, // Receiver is on expression stack.
7753 &receiver_maps,
7754 1,
7755 ast_id,
7756 kCallApiSetter);
7757 }
7758
7759
7760 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
7761 HValue* receiver,
7762 SmallMapList* receiver_maps,
7763 int argc,
7764 BailoutId ast_id,
7765 ApiCallType call_type) {
7766 CallOptimization optimization(function);
7767 if (!optimization.is_simple_api_call()) return false;
7768 Handle<Map> holder_map;
7769 if (call_type == kCallApiFunction) {
7770 // Cannot embed a direct reference to the global proxy map
7771 // as it maybe dropped on deserialization.
7772 CHECK(!Serializer::enabled());
7773 ASSERT_EQ(0, receiver_maps->length());
7774 receiver_maps->Add(handle(
7775 function->context()->global_object()->global_receiver()->map()),
7776 zone());
7777 }
7778 CallOptimization::HolderLookup holder_lookup =
7779 CallOptimization::kHolderNotFound;
7780 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
7781 receiver_maps->first(), &holder_lookup);
7782 if (holder_lookup == CallOptimization::kHolderNotFound) return false;
7783
7784 if (FLAG_trace_inlining) {
7785 PrintF("Inlining api function ");
7786 function->ShortPrint();
7787 PrintF("\n");
7788 }
7789
7790 bool drop_extra = false;
7791 bool is_store = false;
7792 switch (call_type) {
7793 case kCallApiFunction:
7794 case kCallApiMethod:
7795 // Need to check that none of the receiver maps could have changed.
7796 Add<HCheckMaps>(receiver, receiver_maps);
7797 // Need to ensure the chain between receiver and api_holder is intact.
7798 if (holder_lookup == CallOptimization::kHolderFound) {
7799 AddCheckPrototypeMaps(api_holder, receiver_maps->first());
7800 } else {
7801 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
7802 }
7803 // Includes receiver.
7804 PushArgumentsFromEnvironment(argc + 1);
7805 // Drop function after call.
7806 drop_extra = true;
7807 break;
7808 case kCallApiGetter:
7809 // Receiver and prototype chain cannot have changed.
7810 ASSERT_EQ(0, argc);
7811 ASSERT_EQ(NULL, receiver);
7812 // Receiver is on expression stack.
7813 receiver = Pop();
7814 Add<HPushArgument>(receiver);
7815 break;
7816 case kCallApiSetter:
7817 {
7818 is_store = true;
7819 // Receiver and prototype chain cannot have changed.
7820 ASSERT_EQ(1, argc);
7821 ASSERT_EQ(NULL, receiver);
7822 // Receiver and value are on expression stack.
7823 HValue* value = Pop();
7824 receiver = Pop();
7825 Add<HPushArgument>(receiver);
7826 Add<HPushArgument>(value);
7827 break;
7828 }
7829 }
7830
7831 HValue* holder = NULL;
7832 switch (holder_lookup) {
7833 case CallOptimization::kHolderFound:
7834 holder = Add<HConstant>(api_holder);
7835 break;
7836 case CallOptimization::kHolderIsReceiver:
7837 holder = receiver;
7838 break;
7839 case CallOptimization::kHolderNotFound:
7840 UNREACHABLE();
7841 break;
7842 }
7843 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
7844 Handle<Object> call_data_obj(api_call_info->data(), isolate());
7845 bool call_data_is_undefined = call_data_obj->IsUndefined();
7846 HValue* call_data = Add<HConstant>(call_data_obj);
7847 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
7848 ExternalReference ref = ExternalReference(&fun,
7849 ExternalReference::DIRECT_API_CALL,
7850 isolate());
7851 HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
7852
7853 HValue* op_vals[] = {
7854 Add<HConstant>(function),
7855 call_data,
7856 holder,
7857 api_function_address,
7858 context()
7859 };
7860
7861 CallInterfaceDescriptor* descriptor =
7862 isolate()->call_descriptor(Isolate::ApiFunctionCall);
7863
7864 CallApiFunctionStub stub(is_store, call_data_is_undefined, argc);
7865 Handle<Code> code = stub.GetCode(isolate());
7866 HConstant* code_value = Add<HConstant>(code);
7867
7868 ASSERT((sizeof(op_vals) / kPointerSize) ==
7869 descriptor->environment_length());
7870
7871 HInstruction* call = New<HCallWithDescriptor>(
7872 code_value, argc + 1, descriptor,
7873 Vector<HValue*>(op_vals, descriptor->environment_length()));
7874
7875 if (drop_extra) Drop(1); // Drop function.
7876 ast_context()->ReturnInstruction(call, ast_id);
7877 return true;
7878 }
7879
7880
7625 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { 7881 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
7626 Expression* callee = expr->expression(); 7882 ASSERT(expr->expression()->IsProperty());
7627 Property* prop = callee->AsProperty();
7628 ASSERT(prop != NULL);
7629 7883
7630 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 7884 if (!expr->IsMonomorphic()) {
7631 return false; 7885 return false;
7632 } 7886 }
7633 Handle<Map> function_map = expr->GetReceiverTypes()->first(); 7887 Handle<Map> function_map = expr->GetReceiverTypes()->first();
7634 if (function_map->instance_type() != JS_FUNCTION_TYPE || 7888 if (function_map->instance_type() != JS_FUNCTION_TYPE ||
7635 !expr->target()->shared()->HasBuiltinFunctionId() || 7889 !expr->target()->shared()->HasBuiltinFunctionId() ||
7636 expr->target()->shared()->builtin_function_id() != kFunctionApply) { 7890 expr->target()->shared()->builtin_function_id() != kFunctionApply) {
7637 return false; 7891 return false;
7638 } 7892 }
7639 7893
7640 if (current_info()->scope()->arguments() == NULL) return false; 7894 if (current_info()->scope()->arguments() == NULL) return false;
7641 7895
7642 ZoneList<Expression*>* args = expr->arguments(); 7896 ZoneList<Expression*>* args = expr->arguments();
7643 if (args->length() != 2) return false; 7897 if (args->length() != 2) return false;
7644 7898
7645 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 7899 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
7646 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 7900 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
7647 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); 7901 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
7648 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 7902 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
7649 7903
7650 // Found pattern f.apply(receiver, arguments). 7904 // Found pattern f.apply(receiver, arguments).
7651 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true);
7652 HValue* function = Top();
7653
7654 AddCheckConstantFunction(expr->holder(), function, function_map);
7655
7656 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); 7905 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
7657 HValue* receiver = Pop(); 7906 HValue* receiver = Pop(); // receiver
7658 7907 HValue* function = Pop(); // f
7659 Drop(1); // Pop the function. 7908 Drop(1); // apply
7660 7909
7661 if (function_state()->outer() == NULL) { 7910 if (function_state()->outer() == NULL) {
7662 HInstruction* elements = Add<HArgumentsElements>(false); 7911 HInstruction* elements = Add<HArgumentsElements>(false);
7663 HInstruction* length = Add<HArgumentsLength>(elements); 7912 HInstruction* length = Add<HArgumentsLength>(elements);
7664 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); 7913 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function);
7665 HInstruction* result = New<HApplyArguments>(function, 7914 HInstruction* result = New<HApplyArguments>(function,
7666 wrapped_receiver, 7915 wrapped_receiver,
7667 length, 7916 length,
7668 elements); 7917 elements);
7669 ast_context()->ReturnInstruction(result, expr->id()); 7918 ast_context()->ReturnInstruction(result, expr->id());
7670 return true; 7919 return true;
7671 } else { 7920 } else {
7672 // We are inside inlined function and we know exactly what is inside 7921 // We are inside inlined function and we know exactly what is inside
7673 // arguments object. But we need to be able to materialize at deopt. 7922 // arguments object. But we need to be able to materialize at deopt.
7674 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), 7923 ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
7675 function_state()->entry()->arguments_object()->arguments_count()); 7924 function_state()->entry()->arguments_object()->arguments_count());
7676 HArgumentsObject* args = function_state()->entry()->arguments_object(); 7925 HArgumentsObject* args = function_state()->entry()->arguments_object();
7677 const ZoneList<HValue*>* arguments_values = args->arguments_values(); 7926 const ZoneList<HValue*>* arguments_values = args->arguments_values();
7678 int arguments_count = arguments_values->length(); 7927 int arguments_count = arguments_values->length();
7928 Push(function);
7679 Push(BuildWrapReceiver(receiver, function)); 7929 Push(BuildWrapReceiver(receiver, function));
7680 for (int i = 1; i < arguments_count; i++) { 7930 for (int i = 1; i < arguments_count; i++) {
7681 Push(arguments_values->at(i)); 7931 Push(arguments_values->at(i));
7682 } 7932 }
7683 7933
7684 Handle<JSFunction> known_function; 7934 Handle<JSFunction> known_function;
7685 if (function->IsConstant() && 7935 if (function->IsConstant() &&
7686 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { 7936 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
7687 known_function = Handle<JSFunction>::cast( 7937 known_function = Handle<JSFunction>::cast(
7688 HConstant::cast(function)->handle(isolate())); 7938 HConstant::cast(function)->handle(isolate()));
7689 int args_count = arguments_count - 1; // Excluding receiver. 7939 int args_count = arguments_count - 1; // Excluding receiver.
7690 if (TryInlineApply(known_function, expr, args_count)) return true; 7940 if (TryInlineApply(known_function, expr, args_count)) return true;
7691 } 7941 }
7692 7942
7693 Drop(arguments_count - 1); 7943 PushArgumentsFromEnvironment(arguments_count);
7694 Push(Add<HPushArgument>(Pop())); 7944 HInvokeFunction* call = New<HInvokeFunction>(
7695 for (int i = 1; i < arguments_count; i++) { 7945 function, known_function, arguments_count);
7696 Push(Add<HPushArgument>(arguments_values->at(i))); 7946 Drop(1); // Function.
7697 }
7698
7699 HInvokeFunction* call = New<HInvokeFunction>(function,
7700 known_function,
7701 arguments_count);
7702 Drop(arguments_count);
7703 ast_context()->ReturnInstruction(call, expr->id()); 7947 ast_context()->ReturnInstruction(call, expr->id());
7704 return true; 7948 return true;
7705 } 7949 }
7706 } 7950 }
7707 7951
7708 7952
7709 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, 7953 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
7710 Handle<JSFunction> target) { 7954 Handle<JSFunction> target) {
7711 SharedFunctionInfo* shared = target->shared(); 7955 SharedFunctionInfo* shared = target->shared();
7712 if (shared->is_classic_mode() && !shared->native()) { 7956 if (shared->is_classic_mode() && !shared->native()) {
7713 HValue* context = Add<HLoadNamedField>( 7957 // Cannot embed a direct reference to the global proxy
7714 function, 7958 // as is it dropped on deserialization.
7715 HObjectAccess::ForJSObjectOffset(JSFunction::kContextOffset)); 7959 CHECK(!Serializer::enabled());
7716 HValue* global_object = Add<HLoadNamedField>( 7960 Handle<JSObject> global_receiver(
7717 context, 7961 target->context()->global_object()->global_receiver());
7718 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 7962 return Add<HConstant>(global_receiver);
7719 return Add<HLoadNamedField>(
7720 global_object,
7721 HObjectAccess::ForJSObjectOffset(
7722 GlobalObject::kGlobalReceiverOffset));
7723 } 7963 }
7724 return graph()->GetConstantUndefined(); 7964 return graph()->GetConstantUndefined();
7725 } 7965 }
7726 7966
7727 7967
7728 void HOptimizedGraphBuilder::VisitCall(Call* expr) { 7968 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
7729 ASSERT(!HasStackOverflow()); 7969 ASSERT(!HasStackOverflow());
7730 ASSERT(current_block() != NULL); 7970 ASSERT(current_block() != NULL);
7731 ASSERT(current_block()->HasPredecessor()); 7971 ASSERT(current_block()->HasPredecessor());
7732 Expression* callee = expr->expression(); 7972 Expression* callee = expr->expression();
7733 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 7973 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7734 HInstruction* call = NULL; 7974 HInstruction* call = NULL;
7735 7975
7736 Property* prop = callee->AsProperty(); 7976 Property* prop = callee->AsProperty();
7737 if (prop != NULL) { 7977 if (prop != NULL) {
7738 if (!prop->key()->IsPropertyName()) { 7978 CHECK_ALIVE(VisitForValue(prop->obj()));
7739 // Keyed function call. 7979 HValue* receiver = Top();
7740 CHECK_ALIVE(VisitForValue(prop->obj()));
7741 CHECK_ALIVE(VisitForValue(prop->key()));
7742 7980
7743 // Push receiver and key like the non-optimized code generator expects it. 7981 SmallMapList* types;
7744 HValue* key = Pop(); 7982 ComputeReceiverTypes(expr, receiver, &types, zone());
7745 HValue* receiver = Pop();
7746 Push(key);
7747 Push(Add<HPushArgument>(receiver));
7748 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7749 7983
7750 if (expr->IsMonomorphic()) { 7984 if (prop->key()->IsPropertyName() && types->length() > 0) {
7751 BuildCheckHeapObject(receiver); 7985 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
7752 ElementsKind kind = expr->KeyedArrayCallIsHoley() 7986 PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
7753 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; 7987 if (!info.CanAccessAsMonomorphic(types)) {
7754 7988 HandlePolymorphicCallNamed(expr, receiver, types, name);
7755 Handle<Map> map(isolate()->get_initial_js_array_map(kind)); 7989 return;
7756
7757 HValue* function = BuildMonomorphicElementAccess(
7758 receiver, key, NULL, NULL, map, false, STANDARD_STORE);
7759
7760 call = New<HCallFunction>(function, argument_count);
7761 } else {
7762 call = NewCallKeyed(key, argument_count);
7763 } 7990 }
7764 Drop(argument_count + 1); // 1 is the key.
7765 return ast_context()->ReturnInstruction(call, expr->id());
7766 } 7991 }
7767 7992
7768 // Named function call. 7993 HValue* key = NULL;
7769 if (TryCallApply(expr)) return; 7994 if (!prop->key()->IsPropertyName()) {
7770 7995 CHECK_ALIVE(VisitForValue(prop->key()));
7771 CHECK_ALIVE(VisitForValue(prop->obj())); 7996 key = Pop();
7772 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7773
7774 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
7775 HValue* receiver =
7776 environment()->ExpressionStackAt(expr->arguments()->length());
7777
7778 SmallMapList* types;
7779 bool was_monomorphic = expr->IsMonomorphic();
7780 bool monomorphic = ComputeReceiverTypes(expr, receiver, &types);
7781 if (!was_monomorphic && monomorphic) {
7782 monomorphic = expr->ComputeTarget(types->first(), name);
7783 } 7997 }
7784 7998
7785 if (monomorphic) { 7999 CHECK_ALIVE(PushLoad(prop, receiver, key));
7786 Handle<Map> map = types->first(); 8000 HValue* function = Pop();
7787 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) { 8001
8002 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
8003
8004 // Push the function under the receiver.
8005 environment()->SetExpressionStackAt(0, function);
8006
8007 Push(receiver);
8008
8009 if (function->IsConstant() &&
8010 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8011 Handle<JSFunction> known_function = Handle<JSFunction>::cast(
8012 HConstant::cast(function)->handle(isolate()));
8013 expr->set_target(known_function);
8014
8015 if (TryCallApply(expr)) return;
8016 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8017
8018 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
8019 if (TryInlineBuiltinMethodCall(expr, receiver, map)) {
7788 if (FLAG_trace_inlining) { 8020 if (FLAG_trace_inlining) {
7789 PrintF("Inlining builtin "); 8021 PrintF("Inlining builtin ");
7790 expr->target()->ShortPrint(); 8022 known_function->ShortPrint();
7791 PrintF("\n"); 8023 PrintF("\n");
7792 } 8024 }
7793 return; 8025 return;
7794 } 8026 }
8027 if (TryInlineApiMethodCall(expr, receiver, types)) return;
7795 8028
7796 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 8029 // Wrap the receiver if necessary.
7797 expr->check_type() != RECEIVER_MAP_CHECK) { 8030 if (NeedsWrappingFor(ToType(types->first()), known_function)) {
7798 // When the target has a custom call IC generator, use the IC, 8031 // Since HWrapReceiver currently cannot actually wrap numbers and
7799 // because it is likely to generate better code. Also use the IC 8032 // strings, use the regular CallFunctionStub for method calls to wrap
7800 // when a primitive receiver check is required. 8033 // the receiver.
7801 call = NewCallNamed(name, argument_count); 8034 // TODO(verwaest): Support creation of value wrappers directly in
7802 PushArgumentsFromEnvironment(argument_count); 8035 // HWrapReceiver.
8036 call = New<HCallFunction>(
8037 function, argument_count, WRAP_AND_CALL);
8038 } else if (TryInlineCall(expr)) {
8039 return;
7803 } else { 8040 } else {
7804 AddCheckConstantFunction(expr->holder(), receiver, map); 8041 call = BuildCallConstantFunction(known_function, argument_count);
7805
7806 if (TryInlineCall(expr)) return;
7807 call = BuildCallConstantFunction(expr->target(), argument_count);
7808 PushArgumentsFromEnvironment(argument_count);
7809 } 8042 }
7810 } else if (types != NULL && types->length() > 1) {
7811 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
7812 HandlePolymorphicCallNamed(expr, receiver, types, name);
7813 return;
7814 8043
7815 } else { 8044 } else {
7816 call = NewCallNamed(name, argument_count); 8045 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7817 PushArgumentsFromEnvironment(argument_count); 8046 CallFunctionFlags flags = receiver->type().IsJSObject()
8047 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
8048 call = New<HCallFunction>(function, argument_count, flags);
7818 } 8049 }
8050 PushArgumentsFromEnvironment(argument_count);
8051
7819 } else { 8052 } else {
7820 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 8053 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7821 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { 8054 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
7822 return Bailout(kPossibleDirectCallToEval); 8055 return Bailout(kPossibleDirectCallToEval);
7823 } 8056 }
7824 8057
7825 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 8058 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
7826 if (global_call) { 8059 if (global_call) {
7827 Variable* var = proxy->var(); 8060 Variable* var = proxy->var();
7828 bool known_global_function = false; 8061 bool known_global_function = false;
7829 // If there is a global property cell for the name at compile time and 8062 // If there is a global property cell for the name at compile time and
7830 // access check is not enabled we assume that the function will not change 8063 // access check is not enabled we assume that the function will not change
7831 // and generate optimized code for calling the function. 8064 // and generate optimized code for calling the function.
7832 LookupResult lookup(isolate()); 8065 LookupResult lookup(isolate());
7833 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 8066 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD);
7834 if (type == kUseCell && 8067 if (type == kUseCell &&
7835 !current_info()->global_object()->IsAccessCheckNeeded()) { 8068 !current_info()->global_object()->IsAccessCheckNeeded()) {
7836 Handle<GlobalObject> global(current_info()->global_object()); 8069 Handle<GlobalObject> global(current_info()->global_object());
7837 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 8070 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
7838 } 8071 }
8072 CHECK_ALIVE(VisitForValue(expr->expression()));
8073 HValue* function = Top();
7839 if (known_global_function) { 8074 if (known_global_function) {
7840 // Push the global object instead of the global receiver because 8075 Add<HCheckValue>(function, expr->target());
7841 // code generated by the full code generator expects it.
7842 HGlobalObject* global_object = Add<HGlobalObject>();
7843 Push(global_object);
7844 8076
8077 // Placeholder for the receiver.
8078 Push(graph()->GetConstantUndefined());
7845 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8079 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7846 8080
7847 CHECK_ALIVE(VisitForValue(expr->expression()));
7848 HValue* function = Pop();
7849 Add<HCheckValue>(function, expr->target());
7850
7851 // Patch the global object on the stack by the expected receiver. 8081 // Patch the global object on the stack by the expected receiver.
7852 HValue* receiver = ImplicitReceiverFor(function, expr->target()); 8082 HValue* receiver = ImplicitReceiverFor(function, expr->target());
7853 const int receiver_index = argument_count - 1; 8083 const int receiver_index = argument_count - 1;
7854 environment()->SetExpressionStackAt(receiver_index, receiver); 8084 environment()->SetExpressionStackAt(receiver_index, receiver);
7855 8085
7856 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. 8086 if (TryInlineBuiltinFunctionCall(expr)) {
7857 if (FLAG_trace_inlining) { 8087 if (FLAG_trace_inlining) {
7858 PrintF("Inlining builtin "); 8088 PrintF("Inlining builtin ");
7859 expr->target()->ShortPrint(); 8089 expr->target()->ShortPrint();
7860 PrintF("\n"); 8090 PrintF("\n");
7861 } 8091 }
7862 return; 8092 return;
7863 } 8093 }
8094 if (TryInlineApiFunctionCall(expr, receiver)) return;
7864 if (TryInlineCall(expr)) return; 8095 if (TryInlineCall(expr)) return;
7865 8096
7866 if (expr->target().is_identical_to(current_info()->closure())) { 8097 PushArgumentsFromEnvironment(argument_count);
7867 graph()->MarkRecursive(); 8098 call = BuildCallConstantFunction(expr->target(), argument_count);
7868 }
7869
7870 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
7871 // We're about to install a contextual IC, which expects the global
7872 // object as receiver rather than the global proxy.
7873 HGlobalObject* global_object = Add<HGlobalObject>();
7874 const int receiver_index = argument_count - 1;
7875 environment()->SetExpressionStackAt(receiver_index, global_object);
7876 // When the target has a custom call IC generator, use the IC,
7877 // because it is likely to generate better code.
7878 call = NewCallNamed(var->name(), argument_count);
7879 PushArgumentsFromEnvironment(argument_count);
7880 } else {
7881 call = BuildCallConstantFunction(expr->target(), argument_count);
7882 PushArgumentsFromEnvironment(argument_count);
7883 }
7884 } else { 8099 } else {
7885 HGlobalObject* receiver = Add<HGlobalObject>(); 8100 Push(Add<HPushArgument>(graph()->GetConstantUndefined()));
7886 Push(Add<HPushArgument>(receiver));
7887 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 8101 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7888 8102 call = New<HCallFunction>(function, argument_count);
7889 call = NewCallNamed(var->name(), argument_count);
7890 Drop(argument_count); 8103 Drop(argument_count);
7891 } 8104 }
7892 8105
7893 } else if (expr->IsMonomorphic()) { 8106 } else if (expr->IsMonomorphic()) {
7894 // The function is on the stack in the unoptimized code during 8107 // The function is on the stack in the unoptimized code during
7895 // evaluation of the arguments. 8108 // evaluation of the arguments.
7896 CHECK_ALIVE(VisitForValue(expr->expression())); 8109 CHECK_ALIVE(VisitForValue(expr->expression()));
7897 HValue* function = Top(); 8110 HValue* function = Top();
7898 8111
7899 Add<HCheckValue>(function, expr->target()); 8112 Add<HCheckValue>(function, expr->target());
7900 8113
7901 HValue* receiver = ImplicitReceiverFor(function, expr->target()); 8114 Push(graph()->GetConstantUndefined());
7902 Push(receiver);
7903
7904 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8115 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7905 8116
7906 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 8117 HValue* receiver = ImplicitReceiverFor(function, expr->target());
8118 const int receiver_index = argument_count - 1;
8119 environment()->SetExpressionStackAt(receiver_index, receiver);
8120
8121 if (TryInlineBuiltinFunctionCall(expr)) {
7907 if (FLAG_trace_inlining) { 8122 if (FLAG_trace_inlining) {
7908 PrintF("Inlining builtin "); 8123 PrintF("Inlining builtin ");
7909 expr->target()->ShortPrint(); 8124 expr->target()->ShortPrint();
7910 PrintF("\n"); 8125 PrintF("\n");
7911 } 8126 }
7912 return; 8127 return;
7913 } 8128 }
8129 if (TryInlineApiFunctionCall(expr, receiver)) return;
7914 8130
7915 if (TryInlineCall(expr, true)) { // Drop function from environment. 8131 if (TryInlineCall(expr)) return;
7916 return; 8132
7917 } else { 8133 call = PreProcessCall(New<HInvokeFunction>(
7918 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), 8134 function, expr->target(), argument_count));
7919 argument_count));
7920 Drop(1); // The function.
7921 }
7922 8135
7923 } else { 8136 } else {
7924 CHECK_ALIVE(VisitForValue(expr->expression())); 8137 CHECK_ALIVE(VisitForValue(expr->expression()));
7925 HValue* function = Top(); 8138 HValue* function = Top();
7926 HValue* receiver = graph()->GetConstantUndefined(); 8139 HValue* receiver = graph()->GetConstantUndefined();
7927 Push(Add<HPushArgument>(receiver)); 8140 Push(Add<HPushArgument>(receiver));
7928 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 8141 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7929 call = New<HCallFunction>( 8142 call = New<HCallFunction>(function, argument_count);
7930 function, argument_count, NORMAL_CONTEXTUAL_CALL); 8143 Drop(argument_count);
7931 Drop(argument_count + 1);
7932 } 8144 }
7933 } 8145 }
7934 8146
8147 Drop(1); // Drop the function.
7935 return ast_context()->ReturnInstruction(call, expr->id()); 8148 return ast_context()->ReturnInstruction(call, expr->id());
7936 } 8149 }
7937 8150
7938 8151
7939 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { 8152 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) {
7940 NoObservableSideEffectsScope no_effects(this); 8153 NoObservableSideEffectsScope no_effects(this);
7941 8154
7942 int argument_count = expr->arguments()->length(); 8155 int argument_count = expr->arguments()->length();
7943 // We should at least have the constructor on the expression stack. 8156 // We should at least have the constructor on the expression stack.
7944 HValue* constructor = environment()->ExpressionStackAt(argument_count); 8157 HValue* constructor = environment()->ExpressionStackAt(argument_count);
7945 8158
7946 ElementsKind kind = expr->elements_kind(); 8159 ElementsKind kind = expr->elements_kind();
7947 Handle<Cell> cell = expr->allocation_info_cell(); 8160 Handle<AllocationSite> site = expr->allocation_site();
7948 Handle<AllocationSite> site(AllocationSite::cast(cell->value())); 8161 ASSERT(!site.is_null());
7949 8162
7950 // Register on the site for deoptimization if the transition feedback changes. 8163 // Register on the site for deoptimization if the transition feedback changes.
7951 AllocationSite::AddDependentCompilationInfo( 8164 AllocationSite::AddDependentCompilationInfo(
7952 site, AllocationSite::TRANSITIONS, top_info()); 8165 site, AllocationSite::TRANSITIONS, top_info());
7953 HInstruction* site_instruction = Add<HConstant>(site); 8166 HInstruction* site_instruction = Add<HConstant>(site);
7954 8167
7955 // In the single constant argument case, we may have to adjust elements kind 8168 // In the single constant argument case, we may have to adjust elements kind
7956 // to avoid creating a packed non-empty array. 8169 // to avoid creating a packed non-empty array.
7957 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { 8170 if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
7958 HValue* argument = environment()->Top(); 8171 HValue* argument = environment()->Top();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
8005 // Checks whether allocation using the given constructor can be inlined. 8218 // Checks whether allocation using the given constructor can be inlined.
8006 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 8219 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
8007 return constructor->has_initial_map() && 8220 return constructor->has_initial_map() &&
8008 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 8221 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
8009 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && 8222 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
8010 constructor->initial_map()->InitialPropertiesLength() == 0; 8223 constructor->initial_map()->InitialPropertiesLength() == 0;
8011 } 8224 }
8012 8225
8013 8226
8014 bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) { 8227 bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) {
8015 bool inline_ok = false;
8016 Handle<JSFunction> caller = current_info()->closure(); 8228 Handle<JSFunction> caller = current_info()->closure();
8017 Handle<JSFunction> target(isolate()->global_context()->array_function(), 8229 Handle<JSFunction> target(isolate()->native_context()->array_function(),
8018 isolate()); 8230 isolate());
8019 int argument_count = expr->arguments()->length(); 8231 int argument_count = expr->arguments()->length();
8020 // We should have the function plus array arguments on the environment stack. 8232 // We should have the function plus array arguments on the environment stack.
8021 ASSERT(environment()->length() >= (argument_count + 1)); 8233 ASSERT(environment()->length() >= (argument_count + 1));
8022 Handle<Cell> cell = expr->allocation_info_cell(); 8234 Handle<AllocationSite> site = expr->allocation_site();
8023 AllocationSite* site = AllocationSite::cast(cell->value()); 8235 ASSERT(!site.is_null());
8236
8237 bool inline_ok = false;
8024 if (site->CanInlineCall()) { 8238 if (site->CanInlineCall()) {
8025 // We also want to avoid inlining in certain 1 argument scenarios. 8239 // We also want to avoid inlining in certain 1 argument scenarios.
8026 if (argument_count == 1) { 8240 if (argument_count == 1) {
8027 HValue* argument = Top(); 8241 HValue* argument = Top();
8028 if (argument->IsConstant()) { 8242 if (argument->IsConstant()) {
8029 // Do not inline if the constant length argument is not a smi or 8243 // Do not inline if the constant length argument is not a smi or
8030 // outside the valid range for a fast array. 8244 // outside the valid range for a fast array.
8031 HConstant* constant_argument = HConstant::cast(argument); 8245 HConstant* constant_argument = HConstant::cast(argument);
8032 if (constant_argument->HasSmiValue()) { 8246 if (constant_argument->HasSmiValue()) {
8033 int value = constant_argument->Integer32Value(); 8247 int value = constant_argument->Integer32Value();
(...skipping 18 matching lines...) Expand all
8052 TraceInline(target, caller, NULL); 8266 TraceInline(target, caller, NULL);
8053 } 8267 }
8054 return inline_ok; 8268 return inline_ok;
8055 } 8269 }
8056 8270
8057 8271
8058 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 8272 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
8059 ASSERT(!HasStackOverflow()); 8273 ASSERT(!HasStackOverflow());
8060 ASSERT(current_block() != NULL); 8274 ASSERT(current_block() != NULL);
8061 ASSERT(current_block()->HasPredecessor()); 8275 ASSERT(current_block()->HasPredecessor());
8062 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 8276 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
8063 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 8277 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
8064 Factory* factory = isolate()->factory(); 8278 Factory* factory = isolate()->factory();
8065 8279
8066 // The constructor function is on the stack in the unoptimized code 8280 // The constructor function is on the stack in the unoptimized code
8067 // during evaluation of the arguments. 8281 // during evaluation of the arguments.
8068 CHECK_ALIVE(VisitForValue(expr->expression())); 8282 CHECK_ALIVE(VisitForValue(expr->expression()));
8069 HValue* function = Top(); 8283 HValue* function = Top();
8070 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8284 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8071 8285
8072 if (FLAG_inline_construct && 8286 if (FLAG_inline_construct &&
(...skipping 10 matching lines...) Expand all
8083 8297
8084 // Calculate instance size from initial map of constructor. 8298 // Calculate instance size from initial map of constructor.
8085 ASSERT(constructor->has_initial_map()); 8299 ASSERT(constructor->has_initial_map());
8086 Handle<Map> initial_map(constructor->initial_map()); 8300 Handle<Map> initial_map(constructor->initial_map());
8087 int instance_size = initial_map->instance_size(); 8301 int instance_size = initial_map->instance_size();
8088 ASSERT(initial_map->InitialPropertiesLength() == 0); 8302 ASSERT(initial_map->InitialPropertiesLength() == 0);
8089 8303
8090 // Allocate an instance of the implicit receiver object. 8304 // Allocate an instance of the implicit receiver object.
8091 HValue* size_in_bytes = Add<HConstant>(instance_size); 8305 HValue* size_in_bytes = Add<HConstant>(instance_size);
8092 PretenureFlag pretenure_flag = 8306 PretenureFlag pretenure_flag =
8093 (FLAG_pretenuring_call_new && 8307 (FLAG_pretenuring_call_new && !FLAG_allocation_site_pretenuring) ?
8094 isolate()->heap()->GetPretenureMode() == TENURED) 8308 isolate()->heap()->GetPretenureMode() : NOT_TENURED;
8095 ? TENURED : NOT_TENURED;
8096 HAllocate* receiver = 8309 HAllocate* receiver =
8097 Add<HAllocate>(size_in_bytes, HType::JSObject(), pretenure_flag, 8310 Add<HAllocate>(size_in_bytes, HType::JSObject(), pretenure_flag,
8098 JS_OBJECT_TYPE); 8311 JS_OBJECT_TYPE);
8099 receiver->set_known_initial_map(initial_map); 8312 receiver->set_known_initial_map(initial_map);
8100 8313
8101 // Load the initial map from the constructor. 8314 // Load the initial map from the constructor.
8102 HValue* constructor_value = Add<HConstant>(constructor); 8315 HValue* constructor_value = Add<HConstant>(constructor);
8103 HValue* initial_map_value = 8316 HValue* initial_map_value =
8104 Add<HLoadNamedField>(constructor_value, HObjectAccess::ForJSObjectOffset( 8317 Add<HLoadNamedField>(constructor_value, static_cast<HValue*>(NULL),
8105 JSFunction::kPrototypeOrInitialMapOffset)); 8318 HObjectAccess::ForMapAndOffset(
8319 handle(constructor->map()),
8320 JSFunction::kPrototypeOrInitialMapOffset));
8106 8321
8107 // Initialize map and fields of the newly allocated object. 8322 // Initialize map and fields of the newly allocated object.
8108 { NoObservableSideEffectsScope no_effects(this); 8323 { NoObservableSideEffectsScope no_effects(this);
8109 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); 8324 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
8110 Add<HStoreNamedField>(receiver, 8325 Add<HStoreNamedField>(receiver,
8111 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), 8326 HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
8112 initial_map_value); 8327 initial_map_value);
8113 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); 8328 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
8114 Add<HStoreNamedField>(receiver, 8329 Add<HStoreNamedField>(receiver,
8115 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), 8330 HObjectAccess::ForMapAndOffset(initial_map,
8331 JSObject::kPropertiesOffset),
8116 empty_fixed_array); 8332 empty_fixed_array);
8117 Add<HStoreNamedField>(receiver, 8333 Add<HStoreNamedField>(receiver,
8118 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), 8334 HObjectAccess::ForMapAndOffset(initial_map,
8335 JSObject::kElementsOffset),
8119 empty_fixed_array); 8336 empty_fixed_array);
8120 if (initial_map->inobject_properties() != 0) { 8337 if (initial_map->inobject_properties() != 0) {
8121 HConstant* undefined = graph()->GetConstantUndefined(); 8338 HConstant* undefined = graph()->GetConstantUndefined();
8122 for (int i = 0; i < initial_map->inobject_properties(); i++) { 8339 for (int i = 0; i < initial_map->inobject_properties(); i++) {
8123 int property_offset = JSObject::kHeaderSize + i * kPointerSize; 8340 int property_offset = initial_map->GetInObjectPropertyOffset(i);
8124 Add<HStoreNamedField>(receiver, 8341 Add<HStoreNamedField>(receiver,
8125 HObjectAccess::ForJSObjectOffset(property_offset), 8342 HObjectAccess::ForMapAndOffset(initial_map, property_offset),
8126 undefined); 8343 undefined);
8127 } 8344 }
8128 } 8345 }
8129 } 8346 }
8130 8347
8131 // Replace the constructor function with a newly allocated receiver using 8348 // Replace the constructor function with a newly allocated receiver using
8132 // the index of the receiver from the top of the expression stack. 8349 // the index of the receiver from the top of the expression stack.
8133 const int receiver_index = argument_count - 1; 8350 const int receiver_index = argument_count - 1;
8134 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); 8351 ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
8135 environment()->SetExpressionStackAt(receiver_index, receiver); 8352 environment()->SetExpressionStackAt(receiver_index, receiver);
(...skipping 14 matching lines...) Expand all
8150 receiver->DeleteAndReplaceWith(NULL); 8367 receiver->DeleteAndReplaceWith(NULL);
8151 check->DeleteAndReplaceWith(NULL); 8368 check->DeleteAndReplaceWith(NULL);
8152 environment()->SetExpressionStackAt(receiver_index, function); 8369 environment()->SetExpressionStackAt(receiver_index, function);
8153 HInstruction* call = 8370 HInstruction* call =
8154 PreProcessCall(New<HCallNew>(function, argument_count)); 8371 PreProcessCall(New<HCallNew>(function, argument_count));
8155 return ast_context()->ReturnInstruction(call, expr->id()); 8372 return ast_context()->ReturnInstruction(call, expr->id());
8156 } else { 8373 } else {
8157 // The constructor function is both an operand to the instruction and an 8374 // The constructor function is both an operand to the instruction and an
8158 // argument to the construct call. 8375 // argument to the construct call.
8159 Handle<JSFunction> array_function( 8376 Handle<JSFunction> array_function(
8160 isolate()->global_context()->array_function(), isolate()); 8377 isolate()->native_context()->array_function(), isolate());
8161 bool use_call_new_array = expr->target().is_identical_to(array_function); 8378 bool use_call_new_array = expr->target().is_identical_to(array_function);
8162 Handle<Cell> cell = expr->allocation_info_cell();
8163 if (use_call_new_array && IsCallNewArrayInlineable(expr)) { 8379 if (use_call_new_array && IsCallNewArrayInlineable(expr)) {
8164 // Verify we are still calling the array function for our native context. 8380 // Verify we are still calling the array function for our native context.
8165 Add<HCheckValue>(function, array_function); 8381 Add<HCheckValue>(function, array_function);
8166 BuildInlinedCallNewArray(expr); 8382 BuildInlinedCallNewArray(expr);
8167 return; 8383 return;
8168 } 8384 }
8169 8385
8170 HBinaryCall* call; 8386 HBinaryCall* call;
8171 if (use_call_new_array) { 8387 if (use_call_new_array) {
8172 Add<HCheckValue>(function, array_function); 8388 Add<HCheckValue>(function, array_function);
8173 call = New<HCallNewArray>(function, argument_count, cell, 8389 call = New<HCallNewArray>(function, argument_count,
8174 expr->elements_kind()); 8390 expr->elements_kind());
8175 } else { 8391 } else {
8176 call = New<HCallNew>(function, argument_count); 8392 call = New<HCallNew>(function, argument_count);
8177 } 8393 }
8178 PreProcessCall(call); 8394 PreProcessCall(call);
8179 return ast_context()->ReturnInstruction(call, expr->id()); 8395 return ast_context()->ReturnInstruction(call, expr->id());
8180 } 8396 }
8181 } 8397 }
8182 8398
8183 8399
(...skipping 17 matching lines...) Expand all
8201 void HGraphBuilder::BuildArrayBufferViewInitialization( 8417 void HGraphBuilder::BuildArrayBufferViewInitialization(
8202 HValue* obj, 8418 HValue* obj,
8203 HValue* buffer, 8419 HValue* buffer,
8204 HValue* byte_offset, 8420 HValue* byte_offset,
8205 HValue* byte_length) { 8421 HValue* byte_length) {
8206 8422
8207 for (int offset = ViewClass::kSize; 8423 for (int offset = ViewClass::kSize;
8208 offset < ViewClass::kSizeWithInternalFields; 8424 offset < ViewClass::kSizeWithInternalFields;
8209 offset += kPointerSize) { 8425 offset += kPointerSize) {
8210 Add<HStoreNamedField>(obj, 8426 Add<HStoreNamedField>(obj,
8211 HObjectAccess::ForJSObjectOffset(offset), 8427 HObjectAccess::ForObservableJSObjectOffset(offset),
8212 Add<HConstant>(static_cast<int32_t>(0))); 8428 graph()->GetConstant0());
8213 } 8429 }
8214 8430
8215 Add<HStoreNamedField>( 8431 Add<HStoreNamedField>(
8216 obj, 8432 obj,
8217 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); 8433 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
8218 Add<HStoreNamedField>( 8434 Add<HStoreNamedField>(
8219 obj, 8435 obj,
8220 HObjectAccess::ForJSArrayBufferViewByteOffset(), 8436 HObjectAccess::ForJSArrayBufferViewByteOffset(),
8221 byte_offset); 8437 byte_offset);
8222 Add<HStoreNamedField>( 8438 Add<HStoreNamedField>(
8223 obj, 8439 obj,
8224 HObjectAccess::ForJSArrayBufferViewByteLength(), 8440 HObjectAccess::ForJSArrayBufferViewByteLength(),
8225 byte_length); 8441 byte_length);
8226 8442
8227 HObjectAccess weak_first_view_access = 8443 HObjectAccess weak_first_view_access =
8228 HObjectAccess::ForJSArrayBufferWeakFirstView(); 8444 HObjectAccess::ForJSArrayBufferWeakFirstView();
8229 Add<HStoreNamedField>(obj, 8445 Add<HStoreNamedField>(obj,
8230 HObjectAccess::ForJSArrayBufferViewWeakNext(), 8446 HObjectAccess::ForJSArrayBufferViewWeakNext(),
8231 Add<HLoadNamedField>(buffer, weak_first_view_access)); 8447 Add<HLoadNamedField>(buffer, static_cast<HValue*>(NULL),
8232 Add<HStoreNamedField>(buffer, weak_first_view_access, obj); 8448 weak_first_view_access));
8449 Add<HStoreNamedField>(
8450 buffer, weak_first_view_access, obj);
8233 } 8451 }
8234 8452
8235 8453
8236 void HOptimizedGraphBuilder::VisitDataViewInitialize( 8454 void HOptimizedGraphBuilder::VisitDataViewInitialize(
8237 CallRuntime* expr) { 8455 CallRuntime* expr) {
8238 ZoneList<Expression*>* arguments = expr->arguments(); 8456 ZoneList<Expression*>* arguments = expr->arguments();
8239 8457
8240 NoObservableSideEffectsScope scope(this); 8458 NoObservableSideEffectsScope scope(this);
8241 ASSERT(arguments->length()== 4); 8459 ASSERT(arguments->length()== 4);
8242 CHECK_ALIVE(VisitForValue(arguments->at(0))); 8460 CHECK_ALIVE(VisitForValue(arguments->at(0)));
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
8303 8521
8304 if (!is_zero_byte_offset) { 8522 if (!is_zero_byte_offset) {
8305 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); 8523 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
8306 byte_offset_smi.Then(); 8524 byte_offset_smi.Then();
8307 } 8525 }
8308 8526
8309 { // byte_offset is Smi. 8527 { // byte_offset is Smi.
8310 BuildArrayBufferViewInitialization<JSTypedArray>( 8528 BuildArrayBufferViewInitialization<JSTypedArray>(
8311 obj, buffer, byte_offset, byte_length); 8529 obj, buffer, byte_offset, byte_length);
8312 8530
8313 ExternalArrayType array_type = kExternalByteArray; // Bogus initialization. 8531 ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
8314 size_t element_size = 1; // Bogus initialization. 8532 size_t element_size = 1; // Bogus initialization.
8315 Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size); 8533 Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size);
8316 8534
8317 HInstruction* length = AddUncasted<HDiv>(byte_length, 8535 HInstruction* length = AddUncasted<HDiv>(byte_length,
8318 Add<HConstant>(static_cast<int32_t>(element_size))); 8536 Add<HConstant>(static_cast<int32_t>(element_size)));
8319 8537
8320 Add<HStoreNamedField>(obj, 8538 Add<HStoreNamedField>(obj,
8321 HObjectAccess::ForJSTypedArrayLength(), 8539 HObjectAccess::ForJSTypedArrayLength(),
8322 length); 8540 length);
8323 8541
8542 Handle<Map> external_array_map(
8543 isolate()->heap()->MapForExternalArrayType(array_type));
8544
8324 HValue* elements = 8545 HValue* elements =
8325 Add<HAllocate>( 8546 Add<HAllocate>(
8326 Add<HConstant>(ExternalArray::kAlignedSize), 8547 Add<HConstant>(ExternalArray::kAlignedSize),
8327 HType::JSArray(), 8548 HType::JSArray(),
8328 NOT_TENURED, 8549 NOT_TENURED,
8329 static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type)); 8550 external_array_map->instance_type());
8330 8551
8331 Handle<Map> external_array_map( 8552 AddStoreMapConstant(elements, external_array_map);
8332 isolate()->heap()->MapForExternalArrayType(array_type));
8333 Add<HStoreNamedField>(elements,
8334 HObjectAccess::ForMap(),
8335 Add<HConstant>(external_array_map));
8336 8553
8337 HValue* backing_store = Add<HLoadNamedField>( 8554 HValue* backing_store = Add<HLoadNamedField>(
8338 buffer, HObjectAccess::ForJSArrayBufferBackingStore()); 8555 buffer, static_cast<HValue*>(NULL),
8556 HObjectAccess::ForJSArrayBufferBackingStore());
8339 8557
8340 HValue* typed_array_start; 8558 HValue* typed_array_start;
8341 if (is_zero_byte_offset) { 8559 if (is_zero_byte_offset) {
8342 typed_array_start = backing_store; 8560 typed_array_start = backing_store;
8343 } else { 8561 } else {
8344 HInstruction* external_pointer = 8562 HInstruction* external_pointer =
8345 AddUncasted<HAdd>(backing_store, byte_offset); 8563 AddUncasted<HAdd>(backing_store, byte_offset);
8346 // Arguments are checked prior to call to TypedArrayInitialize, 8564 // Arguments are checked prior to call to TypedArrayInitialize,
8347 // including byte_offset. 8565 // including byte_offset.
8348 external_pointer->ClearFlag(HValue::kCanOverflow); 8566 external_pointer->ClearFlag(HValue::kCanOverflow);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
8536 CreateJoin(materialize_false, materialize_true, expr->id()); 8754 CreateJoin(materialize_false, materialize_true, expr->id());
8537 set_current_block(join); 8755 set_current_block(join);
8538 if (join != NULL) return ast_context()->ReturnValue(Pop()); 8756 if (join != NULL) return ast_context()->ReturnValue(Pop());
8539 } 8757 }
8540 8758
8541 8759
8542 HInstruction* HOptimizedGraphBuilder::BuildIncrement( 8760 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
8543 bool returns_original_input, 8761 bool returns_original_input,
8544 CountOperation* expr) { 8762 CountOperation* expr) {
8545 // The input to the count operation is on top of the expression stack. 8763 // The input to the count operation is on top of the expression stack.
8546 Handle<Type> info = expr->type(); 8764 Representation rep = Representation::FromType(expr->type());
8547 Representation rep = Representation::FromType(info);
8548 if (rep.IsNone() || rep.IsTagged()) { 8765 if (rep.IsNone() || rep.IsTagged()) {
8549 rep = Representation::Smi(); 8766 rep = Representation::Smi();
8550 } 8767 }
8551 8768
8552 if (returns_original_input) { 8769 if (returns_original_input) {
8553 // We need an explicit HValue representing ToNumber(input). The 8770 // We need an explicit HValue representing ToNumber(input). The
8554 // actual HChange instruction we need is (sometimes) added in a later 8771 // actual HChange instruction we need is (sometimes) added in a later
8555 // phase, so it is not available now to be used as an input to HAdd and 8772 // phase, so it is not available now to be used as an input to HAdd and
8556 // as the return value. 8773 // as the return value.
8557 HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep); 8774 HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
8592 if (key != NULL) Push(key); 8809 if (key != NULL) Push(key);
8593 Push(value); 8810 Push(value);
8594 BuildStore(expr, prop, ast_id, return_id); 8811 BuildStore(expr, prop, ast_id, return_id);
8595 } 8812 }
8596 8813
8597 8814
8598 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { 8815 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
8599 ASSERT(!HasStackOverflow()); 8816 ASSERT(!HasStackOverflow());
8600 ASSERT(current_block() != NULL); 8817 ASSERT(current_block() != NULL);
8601 ASSERT(current_block()->HasPredecessor()); 8818 ASSERT(current_block()->HasPredecessor());
8602 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 8819 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
8603 Expression* target = expr->expression(); 8820 Expression* target = expr->expression();
8604 VariableProxy* proxy = target->AsVariableProxy(); 8821 VariableProxy* proxy = target->AsVariableProxy();
8605 Property* prop = target->AsProperty(); 8822 Property* prop = target->AsProperty();
8606 if (proxy == NULL && prop == NULL) { 8823 if (proxy == NULL && prop == NULL) {
8607 return Bailout(kInvalidLhsInCountOperation); 8824 return Bailout(kInvalidLhsInCountOperation);
8608 } 8825 }
8609 8826
8610 // Match the full code generator stack by simulating an extra stack 8827 // Match the full code generator stack by simulating an extra stack
8611 // element for postfix operations in a non-effect context. The return 8828 // element for postfix operations in a non-effect context. The return
8612 // value is ToNumber(input). 8829 // value is ToNumber(input).
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
8788 if (right_const->HasInteger32Value() && 9005 if (right_const->HasInteger32Value() &&
8789 (right_const->Integer32Value() & 0x1f) != 0) { 9006 (right_const->Integer32Value() & 0x1f) != 0) {
8790 return false; 9007 return false;
8791 } 9008 }
8792 } 9009 }
8793 return true; 9010 return true;
8794 } 9011 }
8795 9012
8796 9013
8797 HValue* HGraphBuilder::EnforceNumberType(HValue* number, 9014 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
8798 Handle<Type> expected) { 9015 Type* expected) {
8799 if (expected->Is(Type::Smi())) { 9016 if (expected->Is(Type::Smi())) {
8800 return AddUncasted<HForceRepresentation>(number, Representation::Smi()); 9017 return AddUncasted<HForceRepresentation>(number, Representation::Smi());
8801 } 9018 }
8802 if (expected->Is(Type::Signed32())) { 9019 if (expected->Is(Type::Signed32())) {
8803 return AddUncasted<HForceRepresentation>(number, 9020 return AddUncasted<HForceRepresentation>(number,
8804 Representation::Integer32()); 9021 Representation::Integer32());
8805 } 9022 }
8806 return number; 9023 return number;
8807 } 9024 }
8808 9025
8809 9026
8810 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { 9027 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
8811 if (value->IsConstant()) { 9028 if (value->IsConstant()) {
8812 HConstant* constant = HConstant::cast(value); 9029 HConstant* constant = HConstant::cast(value);
8813 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); 9030 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
8814 if (number.has_value) { 9031 if (number.has_value) {
8815 *expected = Type::Number(isolate()); 9032 *expected = Type::Number(zone());
8816 return AddInstruction(number.value); 9033 return AddInstruction(number.value);
8817 } 9034 }
8818 } 9035 }
8819 9036
8820 // We put temporary values on the stack, which don't correspond to anything 9037 // We put temporary values on the stack, which don't correspond to anything
8821 // in baseline code. Since nothing is observable we avoid recording those 9038 // in baseline code. Since nothing is observable we avoid recording those
8822 // pushes with a NoObservableSideEffectsScope. 9039 // pushes with a NoObservableSideEffectsScope.
8823 NoObservableSideEffectsScope no_effects(this); 9040 NoObservableSideEffectsScope no_effects(this);
8824 9041
8825 Handle<Type> expected_type = *expected; 9042 Type* expected_type = *expected;
8826 9043
8827 // Separate the number type from the rest. 9044 // Separate the number type from the rest.
8828 Handle<Type> expected_obj = Type::Intersect( 9045 Type* expected_obj =
8829 expected_type, Type::NonNumber(isolate()), isolate()); 9046 Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
8830 Handle<Type> expected_number = Type::Intersect( 9047 Type* expected_number =
8831 expected_type, Type::Number(isolate()), isolate()); 9048 Type::Intersect(expected_type, Type::Number(zone()), zone());
8832 9049
8833 // We expect to get a number. 9050 // We expect to get a number.
8834 // (We need to check first, since Type::None->Is(Type::Any()) == true. 9051 // (We need to check first, since Type::None->Is(Type::Any()) == true.
8835 if (expected_obj->Is(Type::None())) { 9052 if (expected_obj->Is(Type::None())) {
8836 ASSERT(!expected_number->Is(Type::None())); 9053 ASSERT(!expected_number->Is(Type::None(zone())));
8837 return value; 9054 return value;
8838 } 9055 }
8839 9056
8840 if (expected_obj->Is(Type::Undefined())) { 9057 if (expected_obj->Is(Type::Undefined(zone()))) {
8841 // This is already done by HChange. 9058 // This is already done by HChange.
8842 *expected = Type::Union( 9059 *expected = Type::Union(expected_number, Type::Double(zone()), zone());
8843 expected_number, Type::Double(isolate()), isolate());
8844 return value; 9060 return value;
8845 } 9061 }
8846 9062
8847 return value; 9063 return value;
8848 } 9064 }
8849 9065
8850 9066
8851 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( 9067 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
8852 BinaryOperation* expr, 9068 BinaryOperation* expr,
8853 HValue* left, 9069 HValue* left,
8854 HValue* right) { 9070 HValue* right,
8855 Handle<Type> left_type = expr->left()->bounds().lower; 9071 PushBeforeSimulateBehavior push_sim_result) {
8856 Handle<Type> right_type = expr->right()->bounds().lower; 9072 Type* left_type = expr->left()->bounds().lower;
8857 Handle<Type> result_type = expr->bounds().lower; 9073 Type* right_type = expr->right()->bounds().lower;
9074 Type* result_type = expr->bounds().lower;
8858 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 9075 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
8859 Handle<AllocationSite> allocation_site = expr->allocation_site(); 9076 Handle<AllocationSite> allocation_site = expr->allocation_site();
8860 9077
9078 PretenureFlag pretenure_flag = !FLAG_allocation_site_pretenuring ?
9079 isolate()->heap()->GetPretenureMode() : NOT_TENURED;
9080
8861 HAllocationMode allocation_mode = 9081 HAllocationMode allocation_mode =
8862 FLAG_allocation_site_pretenuring 9082 FLAG_allocation_site_pretenuring
8863 ? (allocation_site.is_null() 9083 ? (allocation_site.is_null()
8864 ? HAllocationMode(NOT_TENURED) 9084 ? HAllocationMode(NOT_TENURED)
8865 : HAllocationMode(allocation_site)) 9085 : HAllocationMode(allocation_site))
8866 : HAllocationMode(isolate()->heap()->GetPretenureMode()); 9086 : HAllocationMode(pretenure_flag);
8867 9087
8868 HValue* result = HGraphBuilder::BuildBinaryOperation( 9088 HValue* result = HGraphBuilder::BuildBinaryOperation(
8869 expr->op(), left, right, left_type, right_type, result_type, 9089 expr->op(), left, right, left_type, right_type, result_type,
8870 fixed_right_arg, allocation_mode); 9090 fixed_right_arg, allocation_mode);
8871 // Add a simulate after instructions with observable side effects, and 9091 // Add a simulate after instructions with observable side effects, and
8872 // after phis, which are the result of BuildBinaryOperation when we 9092 // after phis, which are the result of BuildBinaryOperation when we
8873 // inlined some complex subgraph. 9093 // inlined some complex subgraph.
8874 if (result->HasObservableSideEffects() || result->IsPhi()) { 9094 if (result->HasObservableSideEffects() || result->IsPhi()) {
8875 Push(result); 9095 if (push_sim_result == PUSH_BEFORE_SIMULATE) {
8876 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 9096 Push(result);
8877 Drop(1); 9097 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
9098 Drop(1);
9099 } else {
9100 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
9101 }
8878 } 9102 }
8879 return result; 9103 return result;
8880 } 9104 }
8881 9105
8882 9106
8883 HValue* HGraphBuilder::BuildBinaryOperation( 9107 HValue* HGraphBuilder::BuildBinaryOperation(
8884 Token::Value op, 9108 Token::Value op,
8885 HValue* left, 9109 HValue* left,
8886 HValue* right, 9110 HValue* right,
8887 Handle<Type> left_type, 9111 Type* left_type,
8888 Handle<Type> right_type, 9112 Type* right_type,
8889 Handle<Type> result_type, 9113 Type* result_type,
8890 Maybe<int> fixed_right_arg, 9114 Maybe<int> fixed_right_arg,
8891 HAllocationMode allocation_mode) { 9115 HAllocationMode allocation_mode) {
8892 9116
8893 Representation left_rep = Representation::FromType(left_type); 9117 Representation left_rep = Representation::FromType(left_type);
8894 Representation right_rep = Representation::FromType(right_type); 9118 Representation right_rep = Representation::FromType(right_type);
8895 9119
8896 bool maybe_string_add = op == Token::ADD && 9120 bool maybe_string_add = op == Token::ADD &&
8897 (left_type->Maybe(Type::String()) || 9121 (left_type->Maybe(Type::String()) ||
8898 right_type->Maybe(Type::String())); 9122 right_type->Maybe(Type::String()));
8899 9123
8900 if (left_type->Is(Type::None())) { 9124 if (left_type->Is(Type::None())) {
8901 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", 9125 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
8902 Deoptimizer::SOFT); 9126 Deoptimizer::SOFT);
8903 // TODO(rossberg): we should be able to get rid of non-continuous 9127 // TODO(rossberg): we should be able to get rid of non-continuous
8904 // defaults. 9128 // defaults.
8905 left_type = Type::Any(isolate()); 9129 left_type = Type::Any(zone());
8906 } else { 9130 } else {
8907 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); 9131 if (!maybe_string_add) left = TruncateToNumber(left, &left_type);
8908 left_rep = Representation::FromType(left_type); 9132 left_rep = Representation::FromType(left_type);
8909 } 9133 }
8910 9134
8911 if (right_type->Is(Type::None())) { 9135 if (right_type->Is(Type::None())) {
8912 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", 9136 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
8913 Deoptimizer::SOFT); 9137 Deoptimizer::SOFT);
8914 right_type = Type::Any(isolate()); 9138 right_type = Type::Any(zone());
8915 } else { 9139 } else {
8916 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); 9140 if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
8917 right_rep = Representation::FromType(right_type); 9141 right_rep = Representation::FromType(right_type);
8918 } 9142 }
8919 9143
8920 // Special case for string addition here. 9144 // Special case for string addition here.
8921 if (op == Token::ADD && 9145 if (op == Token::ADD &&
8922 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { 9146 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
8923 // Validate type feedback for left argument. 9147 // Validate type feedback for left argument.
8924 if (left_type->Is(Type::String())) { 9148 if (left_type->Is(Type::String())) {
(...skipping 22 matching lines...) Expand all
8947 ASSERT(left_type->Is(Type::String())); 9171 ASSERT(left_type->Is(Type::String()));
8948 right = BuildNumberToString(right, right_type); 9172 right = BuildNumberToString(right, right_type);
8949 } else if (!right_type->Is(Type::String())) { 9173 } else if (!right_type->Is(Type::String())) {
8950 ASSERT(left_type->Is(Type::String())); 9174 ASSERT(left_type->Is(Type::String()));
8951 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); 9175 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
8952 Add<HPushArgument>(left); 9176 Add<HPushArgument>(left);
8953 Add<HPushArgument>(right); 9177 Add<HPushArgument>(right);
8954 return AddUncasted<HInvokeFunction>(function, 2); 9178 return AddUncasted<HInvokeFunction>(function, 2);
8955 } 9179 }
8956 9180
8957 // Inline the string addition into the stub when creating allocation 9181 // Fast path for empty constant strings.
8958 // mementos to gather allocation site feedback. 9182 if (left->IsConstant() &&
8959 if (graph()->info()->IsStub() && 9183 HConstant::cast(left)->HasStringValue() &&
8960 allocation_mode.CreateAllocationMementos()) { 9184 HConstant::cast(left)->StringValue()->length() == 0) {
8961 return BuildStringAdd(left, right, allocation_mode); 9185 return right;
9186 }
9187 if (right->IsConstant() &&
9188 HConstant::cast(right)->HasStringValue() &&
9189 HConstant::cast(right)->StringValue()->length() == 0) {
9190 return left;
8962 } 9191 }
8963 9192
8964 // Register the dependent code with the allocation site. 9193 // Register the dependent code with the allocation site.
8965 if (!allocation_mode.feedback_site().is_null()) { 9194 if (!allocation_mode.feedback_site().is_null()) {
8966 ASSERT(!graph()->info()->IsStub()); 9195 ASSERT(!graph()->info()->IsStub());
8967 Handle<AllocationSite> site(allocation_mode.feedback_site()); 9196 Handle<AllocationSite> site(allocation_mode.feedback_site());
8968 AllocationSite::AddDependentCompilationInfo( 9197 AllocationSite::AddDependentCompilationInfo(
8969 site, AllocationSite::TENURING, top_info()); 9198 site, AllocationSite::TENURING, top_info());
8970 } 9199 }
8971 9200
8972 // Inline string addition if we know that we'll create a cons string. 9201 // Inline the string addition into the stub when creating allocation
8973 if (left->IsConstant()) { 9202 // mementos to gather allocation site feedback, or if we can statically
8974 HConstant* c_left = HConstant::cast(left); 9203 // infer that we're going to create a cons string.
8975 if (c_left->HasStringValue()) { 9204 if ((graph()->info()->IsStub() &&
8976 int c_left_length = c_left->StringValue()->length(); 9205 allocation_mode.CreateAllocationMementos()) ||
8977 if (c_left_length == 0) { 9206 (left->IsConstant() &&
8978 return right; 9207 HConstant::cast(left)->HasStringValue() &&
8979 } else if (c_left_length + 1 >= ConsString::kMinLength) { 9208 HConstant::cast(left)->StringValue()->length() + 1 >=
8980 return BuildStringAdd(left, right, allocation_mode); 9209 ConsString::kMinLength) ||
8981 } 9210 (right->IsConstant() &&
8982 } 9211 HConstant::cast(right)->HasStringValue() &&
8983 } 9212 HConstant::cast(right)->StringValue()->length() + 1 >=
8984 if (right->IsConstant()) { 9213 ConsString::kMinLength)) {
8985 HConstant* c_right = HConstant::cast(right); 9214 return BuildStringAdd(left, right, allocation_mode);
8986 if (c_right->HasStringValue()) {
8987 int c_right_length = c_right->StringValue()->length();
8988 if (c_right_length == 0) {
8989 return left;
8990 } else if (c_right_length + 1 >= ConsString::kMinLength) {
8991 return BuildStringAdd(left, right, allocation_mode);
8992 }
8993 }
8994 } 9215 }
8995 9216
8996 // Fallback to using the string add stub. 9217 // Fallback to using the string add stub.
8997 return AddUncasted<HStringAdd>( 9218 return AddUncasted<HStringAdd>(
8998 left, right, allocation_mode.GetPretenureMode(), 9219 left, right, allocation_mode.GetPretenureMode(),
8999 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); 9220 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
9000 } 9221 }
9001 9222
9002 if (graph()->info()->IsStub()) { 9223 if (graph()->info()->IsStub()) {
9003 left = EnforceNumberType(left, left_type); 9224 left = EnforceNumberType(left, left_type);
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
9170 eval_right->SetJoinId(expr->RightId()); 9391 eval_right->SetJoinId(expr->RightId());
9171 set_current_block(eval_right); 9392 set_current_block(eval_right);
9172 Visit(expr->right()); 9393 Visit(expr->right());
9173 } 9394 }
9174 9395
9175 } else if (ast_context()->IsValue()) { 9396 } else if (ast_context()->IsValue()) {
9176 CHECK_ALIVE(VisitForValue(expr->left())); 9397 CHECK_ALIVE(VisitForValue(expr->left()));
9177 ASSERT(current_block() != NULL); 9398 ASSERT(current_block() != NULL);
9178 HValue* left_value = Top(); 9399 HValue* left_value = Top();
9179 9400
9180 if (left_value->IsConstant()) { 9401 // Short-circuit left values that always evaluate to the same boolean value.
9181 HConstant* left_constant = HConstant::cast(left_value); 9402 if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
9182 if ((is_logical_and && left_constant->BooleanValue()) || 9403 // l (evals true) && r -> r
9183 (!is_logical_and && !left_constant->BooleanValue())) { 9404 // l (evals true) || r -> l
9184 Drop(1); // left_value. 9405 // l (evals false) && r -> l
9406 // l (evals false) || r -> r
9407 if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
9408 Drop(1);
9185 CHECK_ALIVE(VisitForValue(expr->right())); 9409 CHECK_ALIVE(VisitForValue(expr->right()));
9186 } 9410 }
9187 return ast_context()->ReturnValue(Pop()); 9411 return ast_context()->ReturnValue(Pop());
9188 } 9412 }
9189 9413
9190 // We need an extra block to maintain edge-split form. 9414 // We need an extra block to maintain edge-split form.
9191 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 9415 HBasicBlock* empty_block = graph()->CreateBasicBlock();
9192 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 9416 HBasicBlock* eval_right = graph()->CreateBasicBlock();
9193 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); 9417 ToBooleanStub::Types expected(expr->left()->to_boolean_types());
9194 HBranch* test = is_logical_and 9418 HBranch* test = is_logical_and
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
9247 } 9471 }
9248 } 9472 }
9249 9473
9250 9474
9251 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { 9475 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
9252 CHECK_ALIVE(VisitForValue(expr->left())); 9476 CHECK_ALIVE(VisitForValue(expr->left()));
9253 CHECK_ALIVE(VisitForValue(expr->right())); 9477 CHECK_ALIVE(VisitForValue(expr->right()));
9254 SetSourcePosition(expr->position()); 9478 SetSourcePosition(expr->position());
9255 HValue* right = Pop(); 9479 HValue* right = Pop();
9256 HValue* left = Pop(); 9480 HValue* left = Pop();
9257 HValue* result = BuildBinaryOperation(expr, left, right); 9481 HValue* result =
9258 if (FLAG_emit_opt_code_positions && result->IsBinaryOperation()) { 9482 BuildBinaryOperation(expr, left, right,
9483 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
9484 : PUSH_BEFORE_SIMULATE);
9485 if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) {
9259 HBinaryOperation::cast(result)->SetOperandPositions( 9486 HBinaryOperation::cast(result)->SetOperandPositions(
9260 zone(), expr->left()->position(), expr->right()->position()); 9487 zone(),
9488 ScriptPositionToSourcePosition(expr->left()->position()),
9489 ScriptPositionToSourcePosition(expr->right()->position()));
9261 } 9490 }
9262 return ast_context()->ReturnValue(result); 9491 return ast_context()->ReturnValue(result);
9263 } 9492 }
9264 9493
9265 9494
9266 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 9495 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
9267 Expression* sub_expr, 9496 Expression* sub_expr,
9268 Handle<String> check) { 9497 Handle<String> check) {
9269 CHECK_ALIVE(VisitForTypeOf(sub_expr)); 9498 CHECK_ALIVE(VisitForTypeOf(sub_expr));
9270 SetSourcePosition(expr->position()); 9499 SetSourcePosition(expr->position());
(...skipping 13 matching lines...) Expand all
9284 (right->IsConstant() && 9513 (right->IsConstant() &&
9285 HConstant::cast(right)->handle(isolate)->IsBoolean())); 9514 HConstant::cast(right)->handle(isolate)->IsBoolean()));
9286 } 9515 }
9287 9516
9288 9517
9289 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 9518 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
9290 ASSERT(!HasStackOverflow()); 9519 ASSERT(!HasStackOverflow());
9291 ASSERT(current_block() != NULL); 9520 ASSERT(current_block() != NULL);
9292 ASSERT(current_block()->HasPredecessor()); 9521 ASSERT(current_block()->HasPredecessor());
9293 9522
9294 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 9523 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
9295 9524
9296 // Check for a few fast cases. The AST visiting behavior must be in sync 9525 // Check for a few fast cases. The AST visiting behavior must be in sync
9297 // with the full codegen: We don't push both left and right values onto 9526 // with the full codegen: We don't push both left and right values onto
9298 // the expression stack when one side is a special-case literal. 9527 // the expression stack when one side is a special-case literal.
9299 Expression* sub_expr = NULL; 9528 Expression* sub_expr = NULL;
9300 Handle<String> check; 9529 Handle<String> check;
9301 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { 9530 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
9302 return HandleLiteralCompareTypeof(expr, sub_expr, check); 9531 return HandleLiteralCompareTypeof(expr, sub_expr, check);
9303 } 9532 }
9304 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { 9533 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
9305 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); 9534 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
9306 } 9535 }
9307 if (expr->IsLiteralCompareNull(&sub_expr)) { 9536 if (expr->IsLiteralCompareNull(&sub_expr)) {
9308 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); 9537 return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
9309 } 9538 }
9310 9539
9311 if (IsClassOfTest(expr)) { 9540 if (IsClassOfTest(expr)) {
9312 CallRuntime* call = expr->left()->AsCallRuntime(); 9541 CallRuntime* call = expr->left()->AsCallRuntime();
9313 ASSERT(call->arguments()->length() == 1); 9542 ASSERT(call->arguments()->length() == 1);
9314 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9543 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9315 HValue* value = Pop(); 9544 HValue* value = Pop();
9316 Literal* literal = expr->right()->AsLiteral(); 9545 Literal* literal = expr->right()->AsLiteral();
9317 Handle<String> rhs = Handle<String>::cast(literal->value()); 9546 Handle<String> rhs = Handle<String>::cast(literal->value());
9318 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs); 9547 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
9319 return ast_context()->ReturnControl(instr, expr->id()); 9548 return ast_context()->ReturnControl(instr, expr->id());
9320 } 9549 }
9321 9550
9322 Handle<Type> left_type = expr->left()->bounds().lower; 9551 Type* left_type = expr->left()->bounds().lower;
9323 Handle<Type> right_type = expr->right()->bounds().lower; 9552 Type* right_type = expr->right()->bounds().lower;
9324 Handle<Type> combined_type = expr->combined_type(); 9553 Type* combined_type = expr->combined_type();
9325 9554
9326 CHECK_ALIVE(VisitForValue(expr->left())); 9555 CHECK_ALIVE(VisitForValue(expr->left()));
9327 CHECK_ALIVE(VisitForValue(expr->right())); 9556 CHECK_ALIVE(VisitForValue(expr->right()));
9328 9557
9329 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 9558 if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
9330 9559
9331 HValue* right = Pop(); 9560 HValue* right = Pop();
9332 HValue* left = Pop(); 9561 HValue* left = Pop();
9333 Token::Value op = expr->op(); 9562 Token::Value op = expr->op();
9334 9563
9335 if (IsLiteralCompareBool(isolate(), left, op, right)) { 9564 if (IsLiteralCompareBool(isolate(), left, op, right)) {
9336 HCompareObjectEqAndBranch* result = 9565 HCompareObjectEqAndBranch* result =
9337 New<HCompareObjectEqAndBranch>(left, right); 9566 New<HCompareObjectEqAndBranch>(left, right);
9338 return ast_context()->ReturnControl(result, expr->id()); 9567 return ast_context()->ReturnControl(result, expr->id());
9339 } 9568 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
9379 } else if (op == Token::IN) { 9608 } else if (op == Token::IN) {
9380 HValue* function = AddLoadJSBuiltin(Builtins::IN); 9609 HValue* function = AddLoadJSBuiltin(Builtins::IN);
9381 Add<HPushArgument>(left); 9610 Add<HPushArgument>(left);
9382 Add<HPushArgument>(right); 9611 Add<HPushArgument>(right);
9383 // TODO(olivf) InvokeFunction produces a check for the parameter count, 9612 // TODO(olivf) InvokeFunction produces a check for the parameter count,
9384 // even though we are certain to pass the correct number of arguments here. 9613 // even though we are certain to pass the correct number of arguments here.
9385 HInstruction* result = New<HInvokeFunction>(function, 2); 9614 HInstruction* result = New<HInvokeFunction>(function, 2);
9386 return ast_context()->ReturnInstruction(result, expr->id()); 9615 return ast_context()->ReturnInstruction(result, expr->id());
9387 } 9616 }
9388 9617
9618 PushBeforeSimulateBehavior push_behavior =
9619 ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
9620 : PUSH_BEFORE_SIMULATE;
9389 HControlInstruction* compare = BuildCompareInstruction( 9621 HControlInstruction* compare = BuildCompareInstruction(
9390 op, left, right, left_type, right_type, combined_type, 9622 op, left, right, left_type, right_type, combined_type,
9391 expr->left()->position(), expr->right()->position(), expr->id()); 9623 ScriptPositionToSourcePosition(expr->left()->position()),
9624 ScriptPositionToSourcePosition(expr->right()->position()),
9625 push_behavior, expr->id());
9392 if (compare == NULL) return; // Bailed out. 9626 if (compare == NULL) return; // Bailed out.
9393 return ast_context()->ReturnControl(compare, expr->id()); 9627 return ast_context()->ReturnControl(compare, expr->id());
9394 } 9628 }
9395 9629
9396 9630
9397 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( 9631 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
9398 Token::Value op, 9632 Token::Value op,
9399 HValue* left, 9633 HValue* left,
9400 HValue* right, 9634 HValue* right,
9401 Handle<Type> left_type, 9635 Type* left_type,
9402 Handle<Type> right_type, 9636 Type* right_type,
9403 Handle<Type> combined_type, 9637 Type* combined_type,
9404 int left_position, 9638 HSourcePosition left_position,
9405 int right_position, 9639 HSourcePosition right_position,
9640 PushBeforeSimulateBehavior push_sim_result,
9406 BailoutId bailout_id) { 9641 BailoutId bailout_id) {
9407 // Cases handled below depend on collected type feedback. They should 9642 // Cases handled below depend on collected type feedback. They should
9408 // soft deoptimize when there is no type feedback. 9643 // soft deoptimize when there is no type feedback.
9409 if (combined_type->Is(Type::None())) { 9644 if (combined_type->Is(Type::None())) {
9410 Add<HDeoptimize>("Insufficient type feedback for combined type " 9645 Add<HDeoptimize>("Insufficient type feedback for combined type "
9411 "of binary operation", 9646 "of binary operation",
9412 Deoptimizer::SOFT); 9647 Deoptimizer::SOFT);
9413 combined_type = left_type = right_type = Type::Any(isolate()); 9648 combined_type = left_type = right_type = Type::Any(zone());
9414 } 9649 }
9415 9650
9416 Representation left_rep = Representation::FromType(left_type); 9651 Representation left_rep = Representation::FromType(left_type);
9417 Representation right_rep = Representation::FromType(right_type); 9652 Representation right_rep = Representation::FromType(right_type);
9418 Representation combined_rep = Representation::FromType(combined_type); 9653 Representation combined_rep = Representation::FromType(combined_type);
9419 9654
9420 if (combined_type->Is(Type::Receiver())) { 9655 if (combined_type->Is(Type::Receiver())) {
9421 if (Token::IsEqualityOp(op)) { 9656 if (Token::IsEqualityOp(op)) {
9422 // Can we get away with map check and not instance type check? 9657 // Can we get away with map check and not instance type check?
9423 HValue* operand_to_check = 9658 HValue* operand_to_check =
9424 left->block()->block_id() < right->block()->block_id() ? left : right; 9659 left->block()->block_id() < right->block()->block_id() ? left : right;
9425 if (combined_type->IsClass()) { 9660 if (combined_type->IsClass()) {
9426 Handle<Map> map = combined_type->AsClass(); 9661 Handle<Map> map = combined_type->AsClass();
9427 AddCheckMap(operand_to_check, map); 9662 AddCheckMap(operand_to_check, map);
9428 HCompareObjectEqAndBranch* result = 9663 HCompareObjectEqAndBranch* result =
9429 New<HCompareObjectEqAndBranch>(left, right); 9664 New<HCompareObjectEqAndBranch>(left, right);
9430 if (FLAG_emit_opt_code_positions) { 9665 if (FLAG_hydrogen_track_positions) {
9431 result->set_operand_position(zone(), 0, left_position); 9666 result->set_operand_position(zone(), 0, left_position);
9432 result->set_operand_position(zone(), 1, right_position); 9667 result->set_operand_position(zone(), 1, right_position);
9433 } 9668 }
9434 return result; 9669 return result;
9435 } else { 9670 } else {
9436 BuildCheckHeapObject(operand_to_check); 9671 BuildCheckHeapObject(operand_to_check);
9437 Add<HCheckInstanceType>(operand_to_check, 9672 Add<HCheckInstanceType>(operand_to_check,
9438 HCheckInstanceType::IS_SPEC_OBJECT); 9673 HCheckInstanceType::IS_SPEC_OBJECT);
9439 HCompareObjectEqAndBranch* result = 9674 HCompareObjectEqAndBranch* result =
9440 New<HCompareObjectEqAndBranch>(left, right); 9675 New<HCompareObjectEqAndBranch>(left, right);
(...skipping 19 matching lines...) Expand all
9460 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING); 9695 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
9461 HStringCompareAndBranch* result = 9696 HStringCompareAndBranch* result =
9462 New<HStringCompareAndBranch>(left, right, op); 9697 New<HStringCompareAndBranch>(left, right, op);
9463 return result; 9698 return result;
9464 } else { 9699 } else {
9465 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 9700 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
9466 HCompareGeneric* result = Add<HCompareGeneric>(left, right, op); 9701 HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
9467 result->set_observed_input_representation(1, left_rep); 9702 result->set_observed_input_representation(1, left_rep);
9468 result->set_observed_input_representation(2, right_rep); 9703 result->set_observed_input_representation(2, right_rep);
9469 if (result->HasObservableSideEffects()) { 9704 if (result->HasObservableSideEffects()) {
9470 Push(result); 9705 if (push_sim_result == PUSH_BEFORE_SIMULATE) {
9471 AddSimulate(bailout_id, REMOVABLE_SIMULATE); 9706 Push(result);
9472 Drop(1); 9707 AddSimulate(bailout_id, REMOVABLE_SIMULATE);
9708 Drop(1);
9709 } else {
9710 AddSimulate(bailout_id, REMOVABLE_SIMULATE);
9711 }
9473 } 9712 }
9474 // TODO(jkummerow): Can we make this more efficient? 9713 // TODO(jkummerow): Can we make this more efficient?
9475 HBranch* branch = New<HBranch>(result); 9714 HBranch* branch = New<HBranch>(result);
9476 return branch; 9715 return branch;
9477 } else { 9716 } else {
9478 HCompareNumericAndBranch* result = 9717 HCompareNumericAndBranch* result =
9479 New<HCompareNumericAndBranch>(left, right, op); 9718 New<HCompareNumericAndBranch>(left, right, op);
9480 result->set_observed_input_representation(left_rep, right_rep); 9719 result->set_observed_input_representation(left_rep, right_rep);
9481 if (FLAG_emit_opt_code_positions) { 9720 if (FLAG_hydrogen_track_positions) {
9482 result->SetOperandPositions(zone(), left_position, right_position); 9721 result->SetOperandPositions(zone(), left_position, right_position);
9483 } 9722 }
9484 return result; 9723 return result;
9485 } 9724 }
9486 } 9725 }
9487 } 9726 }
9488 9727
9489 9728
9490 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 9729 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
9491 Expression* sub_expr, 9730 Expression* sub_expr,
9492 NilValue nil) { 9731 NilValue nil) {
9493 ASSERT(!HasStackOverflow()); 9732 ASSERT(!HasStackOverflow());
9494 ASSERT(current_block() != NULL); 9733 ASSERT(current_block() != NULL);
9495 ASSERT(current_block()->HasPredecessor()); 9734 ASSERT(current_block()->HasPredecessor());
9496 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); 9735 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
9497 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 9736 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
9498 CHECK_ALIVE(VisitForValue(sub_expr)); 9737 CHECK_ALIVE(VisitForValue(sub_expr));
9499 HValue* value = Pop(); 9738 HValue* value = Pop();
9500 if (expr->op() == Token::EQ_STRICT) { 9739 if (expr->op() == Token::EQ_STRICT) {
9501 HConstant* nil_constant = nil == kNullValue 9740 HConstant* nil_constant = nil == kNullValue
9502 ? graph()->GetConstantNull() 9741 ? graph()->GetConstantNull()
9503 : graph()->GetConstantUndefined(); 9742 : graph()->GetConstantUndefined();
9504 HCompareObjectEqAndBranch* instr = 9743 HCompareObjectEqAndBranch* instr =
9505 New<HCompareObjectEqAndBranch>(value, nil_constant); 9744 New<HCompareObjectEqAndBranch>(value, nil_constant);
9506 return ast_context()->ReturnControl(instr, expr->id()); 9745 return ast_context()->ReturnControl(instr, expr->id());
9507 } else { 9746 } else {
9508 ASSERT_EQ(Token::EQ, expr->op()); 9747 ASSERT_EQ(Token::EQ, expr->op());
9509 Handle<Type> type = expr->combined_type()->Is(Type::None()) 9748 Type* type = expr->combined_type()->Is(Type::None())
9510 ? Type::Any(isolate_) : expr->combined_type(); 9749 ? Type::Any(zone()) : expr->combined_type();
9511 HIfContinuation continuation; 9750 HIfContinuation continuation;
9512 BuildCompareNil(value, type, &continuation); 9751 BuildCompareNil(value, type, &continuation);
9513 return ast_context()->ReturnContinuation(&continuation, expr->id()); 9752 return ast_context()->ReturnContinuation(&continuation, expr->id());
9514 } 9753 }
9515 } 9754 }
9516 9755
9517 9756
9518 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { 9757 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
9519 // If we share optimized code between different closures, the 9758 // If we share optimized code between different closures, the
9520 // this-function is not a constant, except inside an inlined body. 9759 // this-function is not a constant, except inside an inlined body.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
9554 9793
9555 Handle<FixedArrayBase> elements(boilerplate_object->elements()); 9794 Handle<FixedArrayBase> elements(boilerplate_object->elements());
9556 int elements_size = (elements->length() > 0 && 9795 int elements_size = (elements->length() > 0 &&
9557 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? 9796 elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
9558 elements->Size() : 0; 9797 elements->Size() : 0;
9559 9798
9560 HInstruction* object_elements = NULL; 9799 HInstruction* object_elements = NULL;
9561 if (elements_size > 0) { 9800 if (elements_size > 0) {
9562 HValue* object_elements_size = Add<HConstant>(elements_size); 9801 HValue* object_elements_size = Add<HConstant>(elements_size);
9563 if (boilerplate_object->HasFastDoubleElements()) { 9802 if (boilerplate_object->HasFastDoubleElements()) {
9803 // Allocation folding will not be able to fold |object| and
9804 // |object_elements| together if they are pre-tenured.
9805 if (pretenure_flag == TENURED) {
9806 HConstant* empty_fixed_array = Add<HConstant>(
9807 isolate()->factory()->empty_fixed_array());
9808 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
9809 empty_fixed_array);
9810 }
9564 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), 9811 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(),
9565 pretenure_flag, FIXED_DOUBLE_ARRAY_TYPE, site_context->current()); 9812 pretenure_flag, FIXED_DOUBLE_ARRAY_TYPE, site_context->current());
9566 } else { 9813 } else {
9567 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), 9814 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(),
9568 pretenure_flag, FIXED_ARRAY_TYPE, site_context->current()); 9815 pretenure_flag, FIXED_ARRAY_TYPE, site_context->current());
9569 } 9816 }
9570 } 9817 }
9571 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements); 9818 BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements);
9572 9819
9573 // Copy object elements if non-COW. 9820 // Copy object elements if non-COW.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
9627 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), 9874 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
9628 object_elements); 9875 object_elements);
9629 } 9876 }
9630 9877
9631 9878
9632 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( 9879 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
9633 Handle<JSObject> boilerplate_object, 9880 Handle<JSObject> boilerplate_object,
9634 HInstruction* object, 9881 HInstruction* object,
9635 AllocationSiteUsageContext* site_context, 9882 AllocationSiteUsageContext* site_context,
9636 PretenureFlag pretenure_flag) { 9883 PretenureFlag pretenure_flag) {
9637 Handle<DescriptorArray> descriptors( 9884 Handle<Map> boilerplate_map(boilerplate_object->map());
9638 boilerplate_object->map()->instance_descriptors()); 9885 Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
9639 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); 9886 int limit = boilerplate_map->NumberOfOwnDescriptors();
9640 9887
9641 int copied_fields = 0; 9888 int copied_fields = 0;
9642 for (int i = 0; i < limit; i++) { 9889 for (int i = 0; i < limit; i++) {
9643 PropertyDetails details = descriptors->GetDetails(i); 9890 PropertyDetails details = descriptors->GetDetails(i);
9644 if (details.type() != FIELD) continue; 9891 if (details.type() != FIELD) continue;
9645 copied_fields++; 9892 copied_fields++;
9646 int index = descriptors->GetFieldIndex(i); 9893 int index = descriptors->GetFieldIndex(i);
9647 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); 9894 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
9648 Handle<Name> name(descriptors->GetKey(i)); 9895 Handle<Name> name(descriptors->GetKey(i));
9649 Handle<Object> value = 9896 Handle<Object> value =
9650 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), 9897 Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
9651 isolate()); 9898 isolate());
9652 9899
9653 // The access for the store depends on the type of the boilerplate. 9900 // The access for the store depends on the type of the boilerplate.
9654 HObjectAccess access = boilerplate_object->IsJSArray() ? 9901 HObjectAccess access = boilerplate_object->IsJSArray() ?
9655 HObjectAccess::ForJSArrayOffset(property_offset) : 9902 HObjectAccess::ForJSArrayOffset(property_offset) :
9656 HObjectAccess::ForJSObjectOffset(property_offset); 9903 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
9657 9904
9658 if (value->IsJSObject()) { 9905 if (value->IsJSObject()) {
9659 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 9906 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
9660 Handle<AllocationSite> current_site = site_context->EnterNewScope(); 9907 Handle<AllocationSite> current_site = site_context->EnterNewScope();
9661 HInstruction* result = 9908 HInstruction* result =
9662 BuildFastLiteral(value_object, site_context); 9909 BuildFastLiteral(value_object, site_context);
9663 site_context->ExitScope(current_site, value_object); 9910 site_context->ExitScope(current_site, value_object);
9664 Add<HStoreNamedField>(object, access, result); 9911 Add<HStoreNamedField>(object, access, result);
9665 } else { 9912 } else {
9666 Representation representation = details.representation(); 9913 Representation representation = details.representation();
9667 HInstruction* value_instruction; 9914 HInstruction* value_instruction;
9668 9915
9669 if (representation.IsDouble()) { 9916 if (representation.IsDouble()) {
9670 // Allocate a HeapNumber box and store the value into it. 9917 // Allocate a HeapNumber box and store the value into it.
9671 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); 9918 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
9672 // This heap number alloc does not have a corresponding 9919 // This heap number alloc does not have a corresponding
9673 // AllocationSite. That is okay because 9920 // AllocationSite. That is okay because
9674 // 1) it's a child object of another object with a valid allocation site 9921 // 1) it's a child object of another object with a valid allocation site
9675 // 2) we can just use the mode of the parent object for pretenuring 9922 // 2) we can just use the mode of the parent object for pretenuring
9676 HInstruction* double_box = 9923 HInstruction* double_box =
9677 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), 9924 Add<HAllocate>(heap_number_constant, HType::HeapNumber(),
9678 pretenure_flag, HEAP_NUMBER_TYPE); 9925 pretenure_flag, HEAP_NUMBER_TYPE);
9679 AddStoreMapConstant(double_box, 9926 AddStoreMapConstant(double_box,
9680 isolate()->factory()->heap_number_map()); 9927 isolate()->factory()->heap_number_map());
9681 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), 9928 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(),
9682 Add<HConstant>(value)); 9929 Add<HConstant>(value));
9683 value_instruction = double_box; 9930 value_instruction = double_box;
9684 } else if (representation.IsSmi() && value->IsUninitialized()) { 9931 } else if (representation.IsSmi()) {
9685 value_instruction = graph()->GetConstant0(); 9932 value_instruction = value->IsUninitialized()
9933 ? graph()->GetConstant0()
9934 : Add<HConstant>(value);
9935 // Ensure that value is stored as smi.
9936 access = access.WithRepresentation(representation);
9686 } else { 9937 } else {
9687 value_instruction = Add<HConstant>(value); 9938 value_instruction = Add<HConstant>(value);
9688 } 9939 }
9689 9940
9690 Add<HStoreNamedField>(object, access, value_instruction); 9941 Add<HStoreNamedField>(object, access, value_instruction);
9691 } 9942 }
9692 } 9943 }
9693 9944
9694 int inobject_properties = boilerplate_object->map()->inobject_properties(); 9945 int inobject_properties = boilerplate_object->map()->inobject_properties();
9695 HInstruction* value_instruction = 9946 HInstruction* value_instruction =
9696 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); 9947 Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
9697 for (int i = copied_fields; i < inobject_properties; i++) { 9948 for (int i = copied_fields; i < inobject_properties; i++) {
9698 ASSERT(boilerplate_object->IsJSObject()); 9949 ASSERT(boilerplate_object->IsJSObject());
9699 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); 9950 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
9700 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); 9951 HObjectAccess access =
9952 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
9701 Add<HStoreNamedField>(object, access, value_instruction); 9953 Add<HStoreNamedField>(object, access, value_instruction);
9702 } 9954 }
9703 } 9955 }
9704 9956
9705 9957
9706 void HOptimizedGraphBuilder::BuildEmitElements( 9958 void HOptimizedGraphBuilder::BuildEmitElements(
9707 Handle<JSObject> boilerplate_object, 9959 Handle<JSObject> boilerplate_object,
9708 Handle<FixedArrayBase> elements, 9960 Handle<FixedArrayBase> elements,
9709 HValue* object_elements, 9961 HValue* object_elements,
9710 AllocationSiteUsageContext* site_context) { 9962 AllocationSiteUsageContext* site_context) {
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
10068 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { 10320 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
10069 // The special form detected by IsClassOfTest is detected before we get here 10321 // The special form detected by IsClassOfTest is detected before we get here
10070 // and does not cause a bailout. 10322 // and does not cause a bailout.
10071 return Bailout(kInlinedRuntimeFunctionClassOf); 10323 return Bailout(kInlinedRuntimeFunctionClassOf);
10072 } 10324 }
10073 10325
10074 10326
10075 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { 10327 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
10076 ASSERT(call->arguments()->length() == 1); 10328 ASSERT(call->arguments()->length() == 1);
10077 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10329 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10078 HValue* value = Pop(); 10330 HValue* object = Pop();
10079 HValueOf* result = New<HValueOf>(value); 10331
10080 return ast_context()->ReturnInstruction(result, call->id()); 10332 IfBuilder if_objectisvalue(this);
10333 HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
10334 object, JS_VALUE_TYPE);
10335 if_objectisvalue.Then();
10336 {
10337 // Return the actual value.
10338 Push(Add<HLoadNamedField>(
10339 object, objectisvalue,
10340 HObjectAccess::ForObservableJSObjectOffset(
10341 JSValue::kValueOffset)));
10342 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10343 }
10344 if_objectisvalue.Else();
10345 {
10346 // If the object is not a value return the object.
10347 Push(object);
10348 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10349 }
10350 if_objectisvalue.End();
10351 return ast_context()->ReturnValue(Pop());
10081 } 10352 }
10082 10353
10083 10354
10084 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { 10355 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
10085 ASSERT(call->arguments()->length() == 2); 10356 ASSERT(call->arguments()->length() == 2);
10086 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); 10357 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral());
10087 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value())); 10358 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
10088 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10359 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10089 HValue* date = Pop(); 10360 HValue* date = Pop();
10090 HDateField* result = New<HDateField>(date, index); 10361 HDateField* result = New<HDateField>(date, index);
10091 return ast_context()->ReturnInstruction(result, call->id()); 10362 return ast_context()->ReturnInstruction(result, call->id());
10092 } 10363 }
10093 10364
10094 10365
10095 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( 10366 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
10096 CallRuntime* call) { 10367 CallRuntime* call) {
10097 ASSERT(call->arguments()->length() == 3); 10368 ASSERT(call->arguments()->length() == 3);
10098 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10369 // We need to follow the evaluation order of full codegen.
10099 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10370 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10100 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 10371 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
10372 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10373 HValue* string = Pop();
10101 HValue* value = Pop(); 10374 HValue* value = Pop();
10102 HValue* index = Pop(); 10375 HValue* index = Pop();
10103 HValue* string = Pop();
10104 Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string, 10376 Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
10105 index, value); 10377 index, value);
10106 Add<HSimulate>(call->id(), FIXED_SIMULATE); 10378 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10107 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 10379 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10108 } 10380 }
10109 10381
10110 10382
10111 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( 10383 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
10112 CallRuntime* call) { 10384 CallRuntime* call) {
10113 ASSERT(call->arguments()->length() == 3); 10385 ASSERT(call->arguments()->length() == 3);
10114 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10386 // We need to follow the evaluation order of full codegen.
10115 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10387 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10116 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); 10388 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
10389 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10390 HValue* string = Pop();
10117 HValue* value = Pop(); 10391 HValue* value = Pop();
10118 HValue* index = Pop(); 10392 HValue* index = Pop();
10119 HValue* string = Pop();
10120 Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string, 10393 Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
10121 index, value); 10394 index, value);
10122 Add<HSimulate>(call->id(), FIXED_SIMULATE); 10395 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10123 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 10396 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10124 } 10397 }
10125 10398
10126 10399
10127 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 10400 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
10128 ASSERT(call->arguments()->length() == 2); 10401 ASSERT(call->arguments()->length() == 2);
10129 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10402 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10130 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10403 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10131 HValue* value = Pop(); 10404 HValue* value = Pop();
10132 HValue* object = Pop(); 10405 HValue* object = Pop();
10133 // Check if object is a not a smi.
10134 HBasicBlock* if_smi = graph()->CreateBasicBlock();
10135 HBasicBlock* if_heap_object = graph()->CreateBasicBlock();
10136 HBasicBlock* join = graph()->CreateBasicBlock();
10137 FinishCurrentBlock(New<HIsSmiAndBranch>(object, if_smi, if_heap_object));
10138 Goto(if_smi, join);
10139 10406
10140 // Check if object is a JSValue. 10407 // Check if object is a JSValue.
10141 set_current_block(if_heap_object); 10408 IfBuilder if_objectisvalue(this);
10142 HHasInstanceTypeAndBranch* typecheck = 10409 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
10143 New<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); 10410 if_objectisvalue.Then();
10144 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); 10411 {
10145 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); 10412 // Create in-object property store to kValueOffset.
10146 typecheck->SetSuccessorAt(0, if_js_value); 10413 Add<HStoreNamedField>(object,
10147 typecheck->SetSuccessorAt(1, not_js_value); 10414 HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
10148 FinishCurrentBlock(typecheck); 10415 value);
10149 Goto(not_js_value, join); 10416 if (!ast_context()->IsEffect()) {
10150 10417 Push(value);
10151 // Create in-object property store to kValueOffset. 10418 }
10152 set_current_block(if_js_value); 10419 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10153 Add<HStoreNamedField>(object, 10420 }
10154 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); 10421 if_objectisvalue.Else();
10155 Goto(if_js_value, join); 10422 {
10156 join->SetJoinId(call->id()); 10423 // Nothing to do in this case.
10157 set_current_block(join); 10424 if (!ast_context()->IsEffect()) {
10425 Push(value);
10426 }
10427 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10428 }
10429 if_objectisvalue.End();
10430 if (!ast_context()->IsEffect()) {
10431 Drop(1);
10432 }
10158 return ast_context()->ReturnValue(value); 10433 return ast_context()->ReturnValue(value);
10159 } 10434 }
10160 10435
10161 10436
10162 // Fast support for charCodeAt(n). 10437 // Fast support for charCodeAt(n).
10163 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 10438 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
10164 ASSERT(call->arguments()->length() == 2); 10439 ASSERT(call->arguments()->length() == 2);
10165 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10440 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10166 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10441 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10167 HValue* index = Pop(); 10442 HValue* index = Pop();
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
10252 CHECK_ALIVE(VisitArgumentList(call->arguments())); 10527 CHECK_ALIVE(VisitArgumentList(call->arguments()));
10253 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4); 10528 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
10254 Drop(4); 10529 Drop(4);
10255 return ast_context()->ReturnInstruction(result, call->id()); 10530 return ast_context()->ReturnInstruction(result, call->id());
10256 } 10531 }
10257 10532
10258 10533
10259 // Construct a RegExp exec result with two in-object properties. 10534 // Construct a RegExp exec result with two in-object properties.
10260 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { 10535 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
10261 ASSERT_EQ(3, call->arguments()->length()); 10536 ASSERT_EQ(3, call->arguments()->length());
10262 CHECK_ALIVE(VisitArgumentList(call->arguments())); 10537 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10263 HCallStub* result = New<HCallStub>(CodeStub::RegExpConstructResult, 3); 10538 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10264 Drop(3); 10539 CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
10265 return ast_context()->ReturnInstruction(result, call->id()); 10540 HValue* input = Pop();
10541 HValue* index = Pop();
10542 HValue* length = Pop();
10543 HValue* result = BuildRegExpConstructResult(length, index, input);
10544 return ast_context()->ReturnValue(result);
10266 } 10545 }
10267 10546
10268 10547
10269 // Support for fast native caches. 10548 // Support for fast native caches.
10270 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 10549 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
10271 return Bailout(kInlinedRuntimeFunctionGetFromCache); 10550 return Bailout(kInlinedRuntimeFunctionGetFromCache);
10272 } 10551 }
10273 10552
10274 10553
10275 // Fast support for number to string. 10554 // Fast support for number to string.
10276 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { 10555 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
10277 ASSERT_EQ(1, call->arguments()->length()); 10556 ASSERT_EQ(1, call->arguments()->length());
10278 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10557 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10279 HValue* number = Pop(); 10558 HValue* number = Pop();
10280 HValue* result = BuildNumberToString(number, Type::Number(isolate())); 10559 HValue* result = BuildNumberToString(number, Type::Any(zone()));
10281 return ast_context()->ReturnValue(result); 10560 return ast_context()->ReturnValue(result);
10282 } 10561 }
10283 10562
10284 10563
10285 // Fast call for custom callbacks. 10564 // Fast call for custom callbacks.
10286 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { 10565 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
10287 // 1 ~ The function to call is not itself an argument to the call. 10566 // 1 ~ The function to call is not itself an argument to the call.
10288 int arg_count = call->arguments()->length() - 1; 10567 int arg_count = call->arguments()->length() - 1;
10289 ASSERT(arg_count >= 1); // There's always at least a receiver. 10568 ASSERT(arg_count >= 1); // There's always at least a receiver.
10290 10569
10291 for (int i = 0; i < arg_count; ++i) { 10570 for (int i = 0; i < arg_count; ++i) {
10292 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 10571 CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
10293 } 10572 }
10294 CHECK_ALIVE(VisitForValue(call->arguments()->last())); 10573 CHECK_ALIVE(VisitForValue(call->arguments()->last()));
10295 10574
10296 HValue* function = Pop(); 10575 HValue* function = Pop();
10297 10576
10298 // Branch for function proxies, or other non-functions. 10577 IfBuilder if_is_jsfunction(this);
10299 HHasInstanceTypeAndBranch* typecheck = 10578 if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
10300 New<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
10301 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock();
10302 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock();
10303 HBasicBlock* join = graph()->CreateBasicBlock();
10304 typecheck->SetSuccessorAt(0, if_jsfunction);
10305 typecheck->SetSuccessorAt(1, if_nonfunction);
10306 FinishCurrentBlock(typecheck);
10307 10579
10308 set_current_block(if_jsfunction); 10580 if_is_jsfunction.Then();
10309 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); 10581 {
10310 Drop(arg_count); 10582 HInstruction* invoke_result =
10311 Push(invoke_result); 10583 Add<HInvokeFunction>(function, arg_count);
10312 Goto(if_jsfunction, join); 10584 Drop(arg_count);
10585 if (!ast_context()->IsEffect()) {
10586 Push(invoke_result);
10587 }
10588 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10589 }
10313 10590
10314 set_current_block(if_nonfunction); 10591 if_is_jsfunction.Else();
10315 HInstruction* call_result = Add<HCallFunction>(function, arg_count); 10592 {
10316 Drop(arg_count); 10593 HInstruction* call_result =
10317 Push(call_result); 10594 Add<HCallFunction>(function, arg_count);
10318 Goto(if_nonfunction, join); 10595 Drop(arg_count);
10596 if (!ast_context()->IsEffect()) {
10597 Push(call_result);
10598 }
10599 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10600 }
10601 if_is_jsfunction.End();
10319 10602
10320 set_current_block(join); 10603 if (ast_context()->IsEffect()) {
10321 join->SetJoinId(call->id()); 10604 // EffectContext::ReturnValue ignores the value, so we can just pass
10322 return ast_context()->ReturnValue(Pop()); 10605 // 'undefined' (as we do not have the call result anymore).
10606 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10607 } else {
10608 return ast_context()->ReturnValue(Pop());
10609 }
10323 } 10610 }
10324 10611
10325 10612
10326 // Fast call to math functions. 10613 // Fast call to math functions.
10327 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { 10614 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
10328 ASSERT_EQ(2, call->arguments()->length()); 10615 ASSERT_EQ(2, call->arguments()->length());
10329 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10616 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10330 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 10617 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
10331 HValue* right = Pop(); 10618 HValue* right = Pop();
10332 HValue* left = Pop(); 10619 HValue* left = Pop();
(...skipping 13 matching lines...) Expand all
10346 10633
10347 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 10634 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
10348 ASSERT(call->arguments()->length() == 1); 10635 ASSERT(call->arguments()->length() == 1);
10349 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10636 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10350 HValue* value = Pop(); 10637 HValue* value = Pop();
10351 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); 10638 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
10352 return ast_context()->ReturnInstruction(result, call->id()); 10639 return ast_context()->ReturnInstruction(result, call->id());
10353 } 10640 }
10354 10641
10355 10642
10356 // Check whether two RegExps are equivalent
10357 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
10358 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent);
10359 }
10360
10361
10362 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 10643 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
10363 ASSERT(call->arguments()->length() == 1); 10644 ASSERT(call->arguments()->length() == 1);
10364 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10645 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10365 HValue* value = Pop(); 10646 HValue* value = Pop();
10366 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value); 10647 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
10367 return ast_context()->ReturnInstruction(result, call->id()); 10648 return ast_context()->ReturnInstruction(result, call->id());
10368 } 10649 }
10369 10650
10370 10651
10371 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 10652 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
10684 PrintTo(&trace); 10965 PrintTo(&trace);
10685 PrintF("%s", trace.ToCString().get()); 10966 PrintF("%s", trace.ToCString().get());
10686 } 10967 }
10687 10968
10688 10969
10689 void HTracer::TraceCompilation(CompilationInfo* info) { 10970 void HTracer::TraceCompilation(CompilationInfo* info) {
10690 Tag tag(this, "compilation"); 10971 Tag tag(this, "compilation");
10691 if (info->IsOptimizing()) { 10972 if (info->IsOptimizing()) {
10692 Handle<String> name = info->function()->debug_name(); 10973 Handle<String> name = info->function()->debug_name();
10693 PrintStringProperty("name", name->ToCString().get()); 10974 PrintStringProperty("name", name->ToCString().get());
10694 PrintStringProperty("method", name->ToCString().get()); 10975 PrintIndent();
10976 trace_.Add("method \"%s:%d\"\n",
10977 name->ToCString().get(),
10978 info->optimization_id());
10695 } else { 10979 } else {
10696 CodeStub::Major major_key = info->code_stub()->MajorKey(); 10980 CodeStub::Major major_key = info->code_stub()->MajorKey();
10697 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); 10981 PrintStringProperty("name", CodeStub::MajorName(major_key, false));
10698 PrintStringProperty("method", "stub"); 10982 PrintStringProperty("method", "stub");
10699 } 10983 }
10700 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 10984 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis()));
10701 } 10985 }
10702 10986
10703 10987
10704 void HTracer::TraceLithium(const char* name, LChunk* chunk) { 10988 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
10798 trace_.Add(" "); 11082 trace_.Add(" ");
10799 phi->PrintTo(&trace_); 11083 phi->PrintTo(&trace_);
10800 trace_.Add("\n"); 11084 trace_.Add("\n");
10801 } 11085 }
10802 } 11086 }
10803 11087
10804 { 11088 {
10805 Tag HIR_tag(this, "HIR"); 11089 Tag HIR_tag(this, "HIR");
10806 for (HInstructionIterator it(current); !it.Done(); it.Advance()) { 11090 for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
10807 HInstruction* instruction = it.Current(); 11091 HInstruction* instruction = it.Current();
10808 int bci = FLAG_emit_opt_code_positions && instruction->has_position() ?
10809 instruction->position() : 0;
10810 int uses = instruction->UseCount(); 11092 int uses = instruction->UseCount();
10811 PrintIndent(); 11093 PrintIndent();
10812 trace_.Add("%d %d ", bci, uses); 11094 trace_.Add("0 %d ", uses);
10813 instruction->PrintNameTo(&trace_); 11095 instruction->PrintNameTo(&trace_);
10814 trace_.Add(" "); 11096 trace_.Add(" ");
10815 instruction->PrintTo(&trace_); 11097 instruction->PrintTo(&trace_);
11098 if (FLAG_hydrogen_track_positions &&
11099 instruction->has_position() &&
11100 instruction->position().raw() != 0) {
11101 const HSourcePosition pos = instruction->position();
11102 trace_.Add(" pos:");
11103 if (pos.inlining_id() != 0) {
11104 trace_.Add("%d_", pos.inlining_id());
11105 }
11106 trace_.Add("%d", pos.position());
11107 }
10816 trace_.Add(" <|@\n"); 11108 trace_.Add(" <|@\n");
10817 } 11109 }
10818 } 11110 }
10819 11111
10820 11112
10821 if (chunk != NULL) { 11113 if (chunk != NULL) {
10822 Tag LIR_tag(this, "LIR"); 11114 Tag LIR_tag(this, "LIR");
10823 int first_index = current->first_instruction_index(); 11115 int first_index = current->first_instruction_index();
10824 int last_index = current->last_instruction_index(); 11116 int last_index = current->last_instruction_index();
10825 if (first_index != -1 && last_index != -1) { 11117 if (first_index != -1 && last_index != -1) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
11006 if (ShouldProduceTraceOutput()) { 11298 if (ShouldProduceTraceOutput()) {
11007 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11299 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11008 } 11300 }
11009 11301
11010 #ifdef DEBUG 11302 #ifdef DEBUG
11011 graph_->Verify(false); // No full verify. 11303 graph_->Verify(false); // No full verify.
11012 #endif 11304 #endif
11013 } 11305 }
11014 11306
11015 } } // namespace v8::internal 11307 } } // 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