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

Side by Side Diff: runtime/vm/flow_graph.cc

Issue 10857056: Replaced Value by Definition in the renaming environment. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Patch title. Created 8 years, 4 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 | « runtime/vm/flow_graph.h ('k') | runtime/vm/intermediate_language.h » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph.h" 5 #include "vm/flow_graph.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 } 256 }
257 257
258 258
259 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis) { 259 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis) {
260 // TODO(fschneider): Support catch-entry. 260 // TODO(fschneider): Support catch-entry.
261 if (graph_entry_->SuccessorCount() > 1) { 261 if (graph_entry_->SuccessorCount() > 1) {
262 Bailout("Catch-entry support in SSA."); 262 Bailout("Catch-entry support in SSA.");
263 } 263 }
264 264
265 // Initialize start environment. 265 // Initialize start environment.
266 GrowableArray<Value*> start_env(variable_count()); 266 GrowableArray<Definition*> start_env(variable_count());
267 for (intptr_t i = 0; i < parameter_count(); ++i) { 267 for (intptr_t i = 0; i < parameter_count(); ++i) {
268 ParameterInstr* param = new ParameterInstr(i); 268 ParameterInstr* param = new ParameterInstr(i);
269 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 269 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
270 start_env.Add(new UseVal(param)); 270 start_env.Add(param);
271 } 271 }
272 272
273 // All locals are initialized with #null. 273 // All locals are initialized with #null.
274 Value* null_value = new ConstantVal(Object::ZoneHandle()); 274 Definition* null_def = new BindInstr(BindInstr::kUsed,
275 new ConstantVal(Object::ZoneHandle()));
276 null_def->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
275 while (start_env.length() < variable_count()) { 277 while (start_env.length() < variable_count()) {
276 start_env.Add(null_value); 278 start_env.Add(null_def);
277 } 279 }
278 graph_entry_->set_start_env( 280 graph_entry_->set_start_env(
279 new Environment(start_env, non_copied_parameter_count_)); 281 new Environment(start_env, non_copied_parameter_count_));
280 282
281 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); 283 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
282 ASSERT(normal_entry != NULL); // Must have entry. 284 ASSERT(normal_entry != NULL); // Must have entry.
283 GrowableArray<Value*> env(variable_count()); 285 GrowableArray<Definition*> env(variable_count());
284 env.AddArray(start_env); 286 env.AddArray(start_env);
285 RenameRecursive(normal_entry, &env, live_phis); 287 RenameRecursive(normal_entry, &env, live_phis);
286 } 288 }
287 289
288 290
289 // Helper to a copy a value iff it is a UseVal.
290 static Value* CopyValue(Value* value) {
291 return value->IsUse()
292 ? new UseVal(value->AsUse()->definition())
293 : value;
294 }
295
296
297 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, 291 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
298 GrowableArray<Value*>* env, 292 GrowableArray<Definition*>* env,
299 GrowableArray<PhiInstr*>* live_phis) { 293 GrowableArray<PhiInstr*>* live_phis) {
300 // 1. Process phis first. 294 // 1. Process phis first.
301 if (block_entry->IsJoinEntry()) { 295 if (block_entry->IsJoinEntry()) {
302 JoinEntryInstr* join = block_entry->AsJoinEntry(); 296 JoinEntryInstr* join = block_entry->AsJoinEntry();
303 if (join->phis() != NULL) { 297 if (join->phis() != NULL) {
304 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 298 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
305 PhiInstr* phi = (*join->phis())[i]; 299 PhiInstr* phi = (*join->phis())[i];
306 if (phi != NULL) { 300 if (phi != NULL) {
307 (*env)[i] = new UseVal(phi); 301 (*env)[i] = phi;
308 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 302 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
309 } 303 }
310 } 304 }
311 } 305 }
312 } 306 }
313 307
314 // 2. Process normal instructions. 308 // 2. Process normal instructions.
315 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 309 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
316 Instruction* current = it.Current(); 310 Instruction* current = it.Current();
317 // Attach current environment to the instruction. First, each instruction 311 // Attach current environment to the instruction. First, each instruction
318 // gets a full copy of the environment. Later we optimize this by 312 // gets a full copy of the environment. Later we optimize this by
319 // eliminating unnecessary environments. 313 // eliminating unnecessary environments.
320 current->set_env(new Environment(*env, non_copied_parameter_count_)); 314 current->set_env(new Environment(*env, non_copied_parameter_count_));
321 315
322 // 2a. Handle uses: 316 // 2a. Handle uses:
323 // Update expression stack environment for each use. 317 // Update expression stack environment for each use.
324 // For each use of a LoadLocal or StoreLocal: Replace it with the value 318 // For each use of a LoadLocal or StoreLocal: Replace it with the value
325 // from the environment. 319 // from the environment.
326 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { 320 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
327 Value* v = current->InputAt(i); 321 Value* v = current->InputAt(i);
328 if (!v->IsUse()) continue; 322 if (!v->IsUse()) continue;
329 // Update expression stack. 323 // Update expression stack.
330 ASSERT(env->length() > variable_count()); 324 ASSERT(env->length() > variable_count());
331 325
332 Value* input_value = env->Last(); 326 Definition* input_defn = env->Last();
333 ASSERT(input_value->IsUse());
334 env->RemoveLast(); 327 env->RemoveLast();
335 328
336 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); 329 BindInstr* as_bind = v->AsUse()->definition()->AsBind();
337 if ((as_bind != NULL) && 330 if ((as_bind != NULL) &&
338 (as_bind->computation()->IsLoadLocal() || 331 (as_bind->computation()->IsLoadLocal() ||
339 as_bind->computation()->IsStoreLocal())) { 332 as_bind->computation()->IsStoreLocal())) {
340 // Assert exactly one use. 333 // Assert exactly one use.
341 ASSERT(as_bind->use_list() == v); 334 ASSERT(as_bind->use_list() == v);
342 ASSERT(as_bind->use_list()->next_use() == NULL); 335 ASSERT(as_bind->use_list()->next_use() == NULL);
343 // Remove the use, its definition and copy the environment value. 336 // Remove the use, its definition and copy the environment value.
344 v->RemoveFromUseList(); 337 v->RemoveFromUseList();
345 as_bind->RemoveFromGraph(); 338 as_bind->RemoveFromGraph();
346 current->SetInputAt(i, CopyValue(input_value)); 339 current->SetInputAt(i, new UseVal(input_defn));
347 } 340 }
348 } 341 }
349 342
350 // Drop pushed arguments for calls. 343 // Drop pushed arguments for calls.
351 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { 344 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
352 env->RemoveLast(); 345 env->RemoveLast();
353 } 346 }
354 347
355 // 2b. Handle LoadLocal and StoreLocal. 348 // 2b. Handle LoadLocal and StoreLocal.
356 // For each LoadLocal: Remove it from the graph. 349 // For each LoadLocal: Remove it from the graph.
357 // For each StoreLocal: Remove it from the graph and update the environment. 350 // For each StoreLocal: Remove it from the graph and update the environment.
358 BindInstr* bind = current->AsBind(); 351 BindInstr* bind = current->AsBind();
359 if (bind != NULL) { 352 if (bind != NULL) {
360 LoadLocalComp* load = bind->computation()->AsLoadLocal(); 353 LoadLocalComp* load = bind->computation()->AsLoadLocal();
361 StoreLocalComp* store = bind->computation()->AsStoreLocal(); 354 StoreLocalComp* store = bind->computation()->AsStoreLocal();
362 if ((load != NULL) || (store != NULL)) { 355 if ((load != NULL) || (store != NULL)) {
363 intptr_t index; 356 intptr_t index;
364 if (store != NULL) { 357 if (store != NULL) {
365 index = store->local().BitIndexIn(non_copied_parameter_count_); 358 index = store->local().BitIndexIn(non_copied_parameter_count_);
366 // Update renaming environment. 359 // Update renaming environment.
367 (*env)[index] = store->value(); 360 ASSERT(store->value()->IsUse());
361 (*env)[index] = store->value()->AsUse()->definition();
368 } else { 362 } else {
369 // The graph construction ensures we do not have an unused LoadLocal 363 // The graph construction ensures we do not have an unused LoadLocal
370 // computation. 364 // computation.
371 ASSERT(bind->is_used()); 365 ASSERT(bind->is_used());
372 index = load->local().BitIndexIn(non_copied_parameter_count_); 366 index = load->local().BitIndexIn(non_copied_parameter_count_);
373 367
374 Value* value = (*env)[index]; 368 PhiInstr* phi = (*env)[index]->AsPhi();
375 if (value->IsUse()) { 369 if ((phi != NULL) && !phi->is_alive()) {
376 PhiInstr* phi = value->AsUse()->definition()->AsPhi(); 370 phi->mark_alive();
377 if ((phi != NULL) && !phi->is_alive()) { 371 live_phis->Add(phi);
378 phi->mark_alive();
379 live_phis->Add(phi);
380 }
381 } 372 }
382 } 373 }
383 // Update expression stack or remove from graph. 374 // Update expression stack or remove from graph.
384 if (bind->is_used()) { 375 if (bind->is_used()) {
385 // Assert exactly one use. 376 // Assert exactly one use.
386 ASSERT(bind->use_list() != NULL); 377 ASSERT(bind->use_list() != NULL);
387 ASSERT(bind->use_list()->next_use() == NULL); 378 ASSERT(bind->use_list()->next_use() == NULL);
388 env->Add(CopyValue((*env)[index])); 379 env->Add((*env)[index]);
389 // We remove load/store instructions when we find their use in 2a. 380 // We remove load/store instructions when we find their use in 2a.
390 } else { 381 } else {
391 it.RemoveCurrentFromGraph(); 382 it.RemoveCurrentFromGraph();
392 } 383 }
393 } else { 384 } else {
394 // Not a load or store. 385 // Not a load or store.
395 if (bind->is_used()) { 386 if (bind->is_used()) {
396 // Assign fresh SSA temporary and update expression stack. 387 // Assign fresh SSA temporary and update expression stack.
397 bind->set_ssa_temp_index(alloc_ssa_temp_index()); 388 bind->set_ssa_temp_index(alloc_ssa_temp_index());
398 env->Add(new UseVal(bind)); 389 env->Add(bind);
399 } 390 }
400 } 391 }
401 } 392 }
402 393
403 // 2c. Handle pushed argument. 394 // 2c. Handle pushed argument.
404 PushArgumentInstr* push = current->AsPushArgument(); 395 PushArgumentInstr* push = current->AsPushArgument();
405 if (push != NULL) { 396 if (push != NULL) {
406 env->Add(new UseVal(push)); 397 env->Add(push);
407 } 398 }
408 } 399 }
409 400
410 // 3. Process dominated blocks. 401 // 3. Process dominated blocks.
411 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { 402 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
412 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; 403 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
413 GrowableArray<Value*> new_env(env->length()); 404 GrowableArray<Definition*> new_env(env->length());
414 new_env.AddArray(*env); 405 new_env.AddArray(*env);
415 RenameRecursive(block, &new_env, live_phis); 406 RenameRecursive(block, &new_env, live_phis);
416 } 407 }
417 408
418 // 4. Process successor block. We have edge-split form, so that only blocks 409 // 4. Process successor block. We have edge-split form, so that only blocks
419 // with one successor can have a join block as successor. 410 // with one successor can have a join block as successor.
420 if ((block_entry->last_instruction()->SuccessorCount() == 1) && 411 if ((block_entry->last_instruction()->SuccessorCount() == 1) &&
421 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 412 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
422 JoinEntryInstr* successor = 413 JoinEntryInstr* successor =
423 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 414 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
424 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 415 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
425 ASSERT(pred_index >= 0); 416 ASSERT(pred_index >= 0);
426 if (successor->phis() != NULL) { 417 if (successor->phis() != NULL) {
427 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { 418 for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
428 PhiInstr* phi = (*successor->phis())[i]; 419 PhiInstr* phi = (*successor->phis())[i];
429 if (phi != NULL) { 420 if (phi != NULL) {
430 // Rename input operand and make a copy if it is a UseVal. 421 // Rename input operand.
431 phi->SetInputAt(pred_index, CopyValue((*env)[i])); 422 phi->SetInputAt(pred_index, new UseVal((*env)[i]));
432 } 423 }
433 } 424 }
434 } 425 }
435 } 426 }
436 } 427 }
437 428
438 429
439 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) { 430 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) {
440 while (!live_phis->is_empty()) { 431 while (!live_phis->is_empty()) {
441 PhiInstr* phi = live_phis->Last(); 432 PhiInstr* phi = live_phis->Last();
(...skipping 17 matching lines...) Expand all
459 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 450 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
460 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 451 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
461 OS::SNPrint(chars, len, kFormat, function_name, reason); 452 OS::SNPrint(chars, len, kFormat, function_name, reason);
462 const Error& error = Error::Handle( 453 const Error& error = Error::Handle(
463 LanguageError::New(String::Handle(String::New(chars)))); 454 LanguageError::New(String::Handle(String::New(chars))));
464 Isolate::Current()->long_jump_base()->Jump(1, error); 455 Isolate::Current()->long_jump_base()->Jump(1, error);
465 } 456 }
466 457
467 458
468 } // namespace dart 459 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698