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

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

Issue 9622002: Handle instance field and indexed increment operations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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
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_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "vm/ast_printer.h" 7 #include "vm/ast_printer.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 arguments, Array::ZoneHandle(), 1); 304 arguments, Array::ZoneHandle(), 1);
305 ReturnComputation(call); 305 ReturnComputation(call);
306 } 306 }
307 307
308 308
309 void EffectGraphVisitor::VisitIncrOpLocalNode(IncrOpLocalNode* node) { 309 void EffectGraphVisitor::VisitIncrOpLocalNode(IncrOpLocalNode* node) {
310 Bailout("EffectGraphVisitor::VisitIncrOpLocalNode"); 310 Bailout("EffectGraphVisitor::VisitIncrOpLocalNode");
311 } 311 }
312 312
313 313
314 int EffectGraphVisitor::BuildIncrOpFieldLoad(IncrOpInstanceFieldNode* node,
315 int start_index) {
316 // Evaluate the receiver and duplicate it (it has two uses).
317 // t_n <- ... receiver ...
318 // t_n+1 <- Pick(t_n)
319 ValueGraphVisitor for_receiver(owner(), start_index);
320 node->receiver()->Visit(&for_receiver);
321 Append(for_receiver);
322 ASSERT(for_receiver.value()->IsTemp());
srdjan 2012/03/07 19:12:52 This may not be always be true. A receiver can be
Kevin Millikin (Google) 2012/03/08 11:05:23 Yes, thanks. The bug is that both uses are argume
323 const int receiver_index = for_receiver.value()->AsTemp()->index();
324 const int next_index = for_receiver.temp_index();
srdjan 2012/03/07 19:12:52 ASSERT(next_index = receiver_index + 1)?
Kevin Millikin (Google) 2012/03/08 11:05:23 Done. I got rid of all reliance on the return val
325 AddInstruction(new PickTempInstr(next_index, receiver_index));
326
327 // Load the value.
328 // t_n+1 <- InstanceCall(get:name, t_n+1)
329 const String& getter_name =
330 String::ZoneHandle(Field::GetterSymbol(node->field_name()));
331 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(1);
332 arguments->Add(new TempVal(next_index));
333 InstanceCallComp* load =
334 new InstanceCallComp(node->getter_id(), node->token_index(), getter_name,
335 arguments, Array::ZoneHandle(), 1);
336 AddInstruction(new BindInstr(next_index, load));
337
338 return next_index;
339 }
340
341
342 void EffectGraphVisitor::BuildIncrOpIncrement(Token::Kind kind,
343 intptr_t node_id,
344 intptr_t token_index,
345 int start_index) {
346 ASSERT((kind == Token::kINCR) || (kind == Token::kDECR));
347 // Assumed that t_n-1 (where n is start_index) is the field value.
348 // t_n <- #1
349 // t_n-1 <- InstanceCall(op, t_n-1, t_n)
350 const Smi& one = Smi::ZoneHandle(Smi::New(1));
351 AddInstruction(new BindInstr(start_index, new ConstantVal(one)));
352 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
353 arguments->Add(new TempVal(start_index - 1));
354 arguments->Add(new TempVal(start_index));
355 const String& op_name =
356 String::ZoneHandle(String::NewSymbol((kind == Token::kINCR) ? "+" : "-"));
357 InstanceCallComp* add =
358 new InstanceCallComp(node_id, token_index, op_name,
359 arguments, Array::ZoneHandle(), 2);
360 AddInstruction(new BindInstr(start_index - 1, add));
361 }
362
363
314 void EffectGraphVisitor::VisitIncrOpInstanceFieldNode( 364 void EffectGraphVisitor::VisitIncrOpInstanceFieldNode(
315 IncrOpInstanceFieldNode* node) { 365 IncrOpInstanceFieldNode* node) {
316 Bailout("EffectGraphVisitor::VisitIncrOpInstanceFieldNode"); 366 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR));
367 // Treat postincrement as if it were preincrement.
srdjan 2012/03/07 19:12:52 .. because its results is not needed.
Kevin Millikin (Google) 2012/03/08 11:05:23 Done.
368
369 // 1. Load the value.
370 const int value_index = BuildIncrOpFieldLoad(node, temp_index());
371 // 2. Increment.
372 BuildIncrOpIncrement(node->kind(), node->operator_id(), node->token_index(),
373 value_index + 1);
374 // 3. Perform the store, returning the stored value.
375 InstanceSetterComp* store =
376 new InstanceSetterComp(node->setter_id(), node->token_index(),
377 node->field_name(),
378 new TempVal(value_index - 1),
379 new TempVal(value_index));
380 ReturnComputation(store);
381 }
382
383
384 void ValueGraphVisitor::VisitIncrOpInstanceFieldNode(
385 IncrOpInstanceFieldNode* node) {
386 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR));
387 if (node->prefix()) {
388 // Base class handles preincrement.
389 EffectGraphVisitor::VisitIncrOpInstanceFieldNode(node);
390 return;
391 }
392 // For postincrement, preallocate a temporary to preserve the original
393 // value.
394 //
395 // 1. Name a placeholder.
396 const Smi& placeholder = Smi::ZoneHandle(Smi::New(0));
397 AddInstruction(new BindInstr(temp_index(), new ConstantVal(placeholder)));
srdjan 2012/03/07 19:12:52 placeholder could also be Null object, e.g., Objec
Kevin Millikin (Google) 2012/03/08 11:05:23 Do we have any preference? It's never read except
srdjan 2012/03/08 17:46:09 The difference is only in the source code. To me i
398 // 2. Load the value.
399 const int value_index = BuildIncrOpFieldLoad(node, temp_index() + 1);
400 // 3. Preserve the original value.
401 AddInstruction(new TuckTempInstr(temp_index(), value_index));
402 // 4. Increment.
403 BuildIncrOpIncrement(node->kind(), node->operator_id(), node->token_index(),
404 value_index + 1);
405 // 5. Perform the store and return the original value.
406 const String& setter_name =
407 String::ZoneHandle(Field::SetterSymbol(node->field_name()));
408 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
409 arguments->Add(new TempVal(value_index - 1));
410 arguments->Add(new TempVal(value_index));
411 InstanceCallComp* store =
412 new InstanceCallComp(node->setter_id(), node->token_index(),
413 setter_name, arguments, Array::ZoneHandle(), 1);
414 AddInstruction(new DoInstr(store));
415 ReturnValue(new TempVal(AllocateTempIndex()));
416 }
417
418
419 int EffectGraphVisitor::BuildIncrOpIndexedLoad(IncrOpIndexedNode* node,
420 int start_index) {
421 // Evaluate the receiver and index.
422 // t_n <- ... receiver ...
423 // t_n+1 <- ... index ...
srdjan 2012/03/07 19:12:52 I patched this CL and the code for IncrOpIndexed d
424 ArgumentGraphVisitor for_array(owner(), temp_index());
srdjan 2012/03/07 19:12:52 Indexed access is not for arrays only. I would nam
Kevin Millikin (Google) 2012/03/08 11:05:23 Changed to for_receiver (index and instance were t
425 node->array()->Visit(&for_array);
426 Append(for_array);
427 ASSERT(for_array.value()->IsTemp());
srdjan 2012/03/07 19:12:52 array or receiver could be a constant.
Kevin Millikin (Google) 2012/03/08 11:05:23 ArgumentGraphVisitor should ensure it is named.
428 const int array_index = for_array.value()->AsTemp()->index();
429
430 ArgumentGraphVisitor for_index(owner(), for_array.temp_index());
431 node->index()->Visit(&for_index);
432 Append(for_index);
433 ASSERT(for_index.value()->IsTemp());
434 const int index_index = for_index.value()->AsTemp()->index();
435
436 // Duplicate the receiver and index values, load the value.
437 // t_n+2 <- Pick(t_n)
438 // t_n+3 <- Pick(t_n+1)
439 // t_n+2 <- InstanceCall([], t_n+2, t_n+3)
440 const int next_index = for_index.temp_index();
441 AddInstruction(new PickTempInstr(next_index, array_index));
442 AddInstruction(new PickTempInstr(next_index + 1, index_index));
443 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
444 arguments->Add(new TempVal(next_index));
445 arguments->Add(new TempVal(next_index + 1));
446 const String& load_name =
447 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX)));
448 InstanceCallComp* load =
449 new InstanceCallComp(node->load_id(), node->token_index(), load_name,
450 arguments, Array::ZoneHandle(), 1);
451 AddInstruction(new BindInstr(next_index, load));
452 return next_index;
317 } 453 }
318 454
319 455
320 void EffectGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { 456 void EffectGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) {
321 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); 457 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR));
322 if (node->prefix()) { 458 // Treat postincrement as if it were preincrement.
323 Bailout("IncrOpIndexed prefix");
324 } else {
325 // Leave a placeholder, evaluate receiver and index.
326 // t0 <- #0
327 // t1 <- ... receiver ...
328 // t2 <- ... index ...
329 const Smi& placeholder = Smi::ZoneHandle(Smi::New(0));
330 const int placeholder_index = temp_index();
331 AddInstruction(new BindInstr(placeholder_index,
332 new ConstantVal(placeholder)));
333 459
334 ArgumentGraphVisitor for_array(owner(), temp_index() + 1); 460 // 1. Load the value.
335 node->array()->Visit(&for_array); 461 const int value_index = BuildIncrOpIndexedLoad(node, temp_index());
336 Append(for_array); 462 // 2. Increment.
337 ASSERT(for_array.value()->IsTemp()); 463 BuildIncrOpIncrement(node->kind(), node->operator_id(), node->token_index(),
338 const int array_index = for_array.value()->AsTemp()->index(); 464 value_index + 1);
339 465 // 3. Perform the store, returning the stored value.
340 ArgumentGraphVisitor for_index(owner(), for_array.temp_index()); 466 StoreIndexedComp* store = new StoreIndexedComp(node->store_id(),
341 node->index()->Visit(&for_index); 467 node->token_index(),
342 Append(for_index); 468 new TempVal(value_index - 2),
343 ASSERT(for_index.value()->IsTemp()); 469 new TempVal(value_index - 1),
344 const int index_index = for_index.value()->AsTemp()->index(); 470 new TempVal(value_index));
345 471 ReturnComputation(store);
346 // Duplicate the receiver and index values, load the value.
347 // t3 <- Pick(t1)
348 // t4 <- Pick(t2)
349 // t3 <- InstanceCall([], t3, t4)
350 int next_index = for_index.temp_index();
351 AddInstruction(new PickTempInstr(next_index, array_index));
352 AddInstruction(new PickTempInstr(next_index + 1, index_index));
353 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2);
354 arguments->Add(new TempVal(next_index));
355 arguments->Add(new TempVal(next_index + 1));
356 const String& load_name =
357 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kINDEX)));
358 InstanceCallComp* load =
359 new InstanceCallComp(node->load_id(), node->token_index(), load_name,
360 arguments, Array::ZoneHandle(), 1);
361 AddInstruction(new BindInstr(next_index, load));
362
363 // Preserve the original value and then increment.
364 // t0 := t3
365 // t4 <- #1
366 // t3 <- InstanceCall(op, t3, t4)
367 AddInstruction(new TuckTempInstr(placeholder_index, next_index));
368 const Smi& one = Smi::ZoneHandle(Smi::New(1));
369 AddInstruction(new BindInstr(next_index + 1, new ConstantVal(one)));
370 arguments = new ZoneGrowableArray<Value*>(2);
371 arguments->Add(new TempVal(next_index));
372 arguments->Add(new TempVal(next_index + 1));
373 const String& op_name = String::ZoneHandle(String::NewSymbol(
374 (node->kind() == Token::kINCR) ? "+" : "-"));
375 InstanceCallComp* add =
376 new InstanceCallComp(node->operator_id(), node->token_index(), op_name,
377 arguments, Array::ZoneHandle(), 2);
378 AddInstruction(new BindInstr(next_index, add));
379
380 // Perform the store.
381 // InstanceCallComp([]=, t1, t2, t3)
382 // ... value is t0 ...
383 arguments = new ZoneGrowableArray<Value*>(3);
384 arguments->Add(for_array.value());
385 arguments->Add(for_index.value());
386 arguments->Add(new TempVal(next_index));
387 const String& store_name =
388 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX)));
389 InstanceCallComp* store =
390 new InstanceCallComp(node->store_id(), node->token_index(), store_name,
391 arguments, Array::ZoneHandle(), 1);
392 AddInstruction(new DoInstr(store));
393
394 ReturnValue(new TempVal(AllocateTempIndex()));
395 }
396 } 472 }
397 473
398 474
475 void ValueGraphVisitor::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) {
476 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR));
477 if (node->prefix()) {
478 // Base class handles preincrement.
479 EffectGraphVisitor::VisitIncrOpIndexedNode(node);
480 return;
481 }
482 // For postincrement, preallocate a temporary to preserve the original
483 // value.
484 //
485 // 1. Name a placeholder.
486 const Smi& placeholder = Smi::ZoneHandle(Smi::New(0));
487 AddInstruction(new BindInstr(temp_index(), new ConstantVal(placeholder)));
srdjan 2012/03/07 19:12:52 placeholder could be Object::Handle() (null object
488 // 2. Load the value.
489 const int value_index = BuildIncrOpIndexedLoad(node, temp_index() + 1);
srdjan 2012/03/07 19:12:52 The bug: loaded receiver will be store in the same
Kevin Millikin (Google) 2012/03/08 11:05:23 Good catch and thanks for the test case. Renaming
490 // 3. Preserve the original value.
491 AddInstruction(new TuckTempInstr(temp_index(), value_index));
492 // 4. Increment.
493 BuildIncrOpIncrement(node->kind(), node->operator_id(), node->token_index(),
494 value_index + 1);
495 // 5. Perform the store and return the original value.
496 const String& store_name =
497 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX)));
498 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(3);
499 arguments->Add(new TempVal(value_index - 2));
500 arguments->Add(new TempVal(value_index - 1));
501 arguments->Add(new TempVal(value_index));
502 InstanceCallComp* store =
503 new InstanceCallComp(node->store_id(), node->token_index(), store_name,
504 arguments, Array::ZoneHandle(), 1);
505 AddInstruction(new DoInstr(store));
506 ReturnValue(new TempVal(AllocateTempIndex()));
507 }
508
509
399 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { 510 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) {
400 Bailout("EffectGraphVisitor::VisitConditionalExprNode"); 511 Bailout("EffectGraphVisitor::VisitConditionalExprNode");
401 } 512 }
402 513
403 514
404 // <Statement> ::= If { condition: <Expression> 515 // <Statement> ::= If { condition: <Expression>
405 // true_branch: <Sequence> 516 // true_branch: <Sequence>
406 // false_branch: <Sequence> } 517 // false_branch: <Sequence> }
407 void EffectGraphVisitor::VisitIfNode(IfNode* node) { 518 void EffectGraphVisitor::VisitIfNode(IfNode* node) {
408 TestGraphVisitor for_test(owner(), temp_index()); 519 TestGraphVisitor for_test(owner(), temp_index());
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 } 677 }
567 678
568 679
569 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { 680 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
570 ArgumentGraphVisitor for_receiver(owner(), temp_index()); 681 ArgumentGraphVisitor for_receiver(owner(), temp_index());
571 node->receiver()->Visit(&for_receiver); 682 node->receiver()->Visit(&for_receiver);
572 Append(for_receiver); 683 Append(for_receiver);
573 ArgumentGraphVisitor for_value(owner(), for_receiver.temp_index()); 684 ArgumentGraphVisitor for_value(owner(), for_receiver.temp_index());
574 node->value()->Visit(&for_value); 685 node->value()->Visit(&for_value);
575 Append(for_value); 686 Append(for_value);
576 InstanceSetterComp* setter = new InstanceSetterComp(node, 687 InstanceSetterComp* setter = new InstanceSetterComp(node->id(),
688 node->token_index(),
689 node->field_name(),
577 for_receiver.value(), 690 for_receiver.value(),
578 for_value.value()); 691 for_value.value());
579 ReturnComputation(setter); 692 ReturnComputation(setter);
580 } 693 }
581 694
582 695
583 void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { 696 void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) {
584 Bailout("EffectGraphVisitor::VisitStaticGetterNode"); 697 Bailout("EffectGraphVisitor::VisitStaticGetterNode");
585 } 698 }
586 699
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 node->value()->Visit(&for_value); 793 node->value()->Visit(&for_value);
681 Append(for_value); 794 Append(for_value);
682 Value* store_value = for_value.value(); 795 Value* store_value = for_value.value();
683 if (FLAG_enable_type_checks) { 796 if (FLAG_enable_type_checks) {
684 const AbstractType& type = AbstractType::ZoneHandle(node->field().type()); 797 const AbstractType& type = AbstractType::ZoneHandle(node->field().type());
685 AssertAssignableComp* assert = new AssertAssignableComp(store_value, type); 798 AssertAssignableComp* assert = new AssertAssignableComp(store_value, type);
686 AddInstruction(new BindInstr(temp_index(), assert)); 799 AddInstruction(new BindInstr(temp_index(), assert));
687 store_value = new TempVal(temp_index()); 800 store_value = new TempVal(temp_index());
688 } 801 }
689 StoreStaticFieldComp* store = 802 StoreStaticFieldComp* store =
690 new StoreStaticFieldComp(node, store_value); 803 new StoreStaticFieldComp(node->field(), store_value);
691 ReturnComputation(store); 804 ReturnComputation(store);
692 } 805 }
693 806
694 807
695 void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) { 808 void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) {
696 ArgumentGraphVisitor for_array(owner(), temp_index()); 809 ArgumentGraphVisitor for_array(owner(), temp_index());
697 node->array()->Visit(&for_array); 810 node->array()->Visit(&for_array);
698 Append(for_array); 811 Append(for_array);
699 ArgumentGraphVisitor for_index(owner(), for_array.temp_index()); 812 ArgumentGraphVisitor for_index(owner(), for_array.temp_index());
700 node->index_expr()->Visit(&for_index); 813 node->index_expr()->Visit(&for_index);
(...skipping 13 matching lines...) Expand all
714 void EffectGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { 827 void EffectGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) {
715 ArgumentGraphVisitor for_array(owner(), temp_index()); 828 ArgumentGraphVisitor for_array(owner(), temp_index());
716 node->array()->Visit(&for_array); 829 node->array()->Visit(&for_array);
717 Append(for_array); 830 Append(for_array);
718 ArgumentGraphVisitor for_index(owner(), for_array.temp_index()); 831 ArgumentGraphVisitor for_index(owner(), for_array.temp_index());
719 node->index_expr()->Visit(&for_index); 832 node->index_expr()->Visit(&for_index);
720 Append(for_index); 833 Append(for_index);
721 ArgumentGraphVisitor for_value(owner(), for_index.temp_index()); 834 ArgumentGraphVisitor for_value(owner(), for_index.temp_index());
722 node->value()->Visit(&for_value); 835 node->value()->Visit(&for_value);
723 Append(for_value); 836 Append(for_value);
724 StoreIndexedComp* store = new StoreIndexedComp(node, 837 StoreIndexedComp* store = new StoreIndexedComp(node->id(),
838 node->token_index(),
725 for_array.value(), 839 for_array.value(),
726 for_index.value(), 840 for_index.value(),
727 for_value.value()); 841 for_value.value());
728 ReturnComputation(store); 842 ReturnComputation(store);
729 } 843 }
730 844
731 845
732 // <Statement> ::= Sequence { scope: LocalScope 846 // <Statement> ::= Sequence { scope: LocalScope
733 // nodes: <Statement>* 847 // nodes: <Statement>*
734 // label: SourceLabel } 848 // label: SourceLabel }
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 char* chars = reinterpret_cast<char*>( 1131 char* chars = reinterpret_cast<char*>(
1018 Isolate::Current()->current_zone()->Allocate(len)); 1132 Isolate::Current()->current_zone()->Allocate(len));
1019 OS::SNPrint(chars, len, kFormat, function_name, reason); 1133 OS::SNPrint(chars, len, kFormat, function_name, reason);
1020 const Error& error = Error::Handle( 1134 const Error& error = Error::Handle(
1021 LanguageError::New(String::Handle(String::New(chars)))); 1135 LanguageError::New(String::Handle(String::New(chars))));
1022 Isolate::Current()->long_jump_base()->Jump(1, error); 1136 Isolate::Current()->long_jump_base()->Jump(1, error);
1023 } 1137 }
1024 1138
1025 1139
1026 } // namespace dart 1140 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698