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

Side by Side Diff: v8/src/codegen-ia32.cc

Issue 11229: Experimental: change the name of the VirtualFrame function Push to... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 12 years, 1 month 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 | « v8/src/codegen-arm.cc ('k') | v8/src/virtual-frame-arm.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 bool arguments_object_saved = false; 139 bool arguments_object_saved = false;
140 140
141 // Allocate arguments object. 141 // Allocate arguments object.
142 // The arguments object pointer needs to be saved in ecx, since we need 142 // The arguments object pointer needs to be saved in ecx, since we need
143 // to store arguments into the context. 143 // to store arguments into the context.
144 if (scope_->arguments() != NULL) { 144 if (scope_->arguments() != NULL) {
145 ASSERT(scope_->arguments_shadow() != NULL); 145 ASSERT(scope_->arguments_shadow() != NULL);
146 Comment cmnt(masm_, "[ allocate arguments object"); 146 Comment cmnt(masm_, "[ allocate arguments object");
147 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 147 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
148 __ lea(eax, frame_->Receiver()); 148 __ lea(eax, frame_->Receiver());
149 frame_->Push(frame_->Function()); 149 frame_->EmitPush(frame_->Function());
150 frame_->Push(eax); 150 frame_->EmitPush(eax);
151 frame_->Push(Immediate(Smi::FromInt(scope_->num_parameters()))); 151 frame_->EmitPush(Immediate(Smi::FromInt(scope_->num_parameters())));
152 frame_->CallStub(&stub, 3); 152 frame_->CallStub(&stub, 3);
153 __ mov(ecx, Operand(eax)); 153 __ mov(ecx, Operand(eax));
154 arguments_object_allocated = true; 154 arguments_object_allocated = true;
155 } 155 }
156 156
157 // Allocate space for locals and initialize them. 157 // Allocate space for locals and initialize them.
158 frame_->AllocateStackSlots(scope_->num_stack_slots()); 158 frame_->AllocateStackSlots(scope_->num_stack_slots());
159 159
160 if (scope_->num_heap_slots() > 0) { 160 if (scope_->num_heap_slots() > 0) {
161 Comment cmnt(masm_, "[ allocate local context"); 161 Comment cmnt(masm_, "[ allocate local context");
162 // Save the arguments object pointer, if any. 162 // Save the arguments object pointer, if any.
163 if (arguments_object_allocated && !arguments_object_saved) { 163 if (arguments_object_allocated && !arguments_object_saved) {
164 frame_->Push(ecx); 164 frame_->EmitPush(ecx);
165 arguments_object_saved = true; 165 arguments_object_saved = true;
166 } 166 }
167 // Allocate local context. 167 // Allocate local context.
168 // Get outer context and create a new context based on it. 168 // Get outer context and create a new context based on it.
169 frame_->Push(frame_->Function()); 169 frame_->EmitPush(frame_->Function());
170 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result 170 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result
171 171
172 if (kDebug) { 172 if (kDebug) {
173 JumpTarget verified_true(this); 173 JumpTarget verified_true(this);
174 // Verify eax and esi are the same in debug mode 174 // Verify eax and esi are the same in debug mode
175 __ cmp(eax, Operand(esi)); 175 __ cmp(eax, Operand(esi));
176 verified_true.Branch(equal); 176 verified_true.Branch(equal);
177 __ int3(); 177 __ int3();
178 verified_true.Bind(); 178 verified_true.Bind();
179 } 179 }
(...skipping 15 matching lines...) Expand all
195 // case so we don't check for it, instead we rely on the copying 195 // case so we don't check for it, instead we rely on the copying
196 // order: such a parameter is copied repeatedly into the same 196 // order: such a parameter is copied repeatedly into the same
197 // context location and thus the last value is what is seen inside 197 // context location and thus the last value is what is seen inside
198 // the function. 198 // the function.
199 for (int i = 0; i < scope_->num_parameters(); i++) { 199 for (int i = 0; i < scope_->num_parameters(); i++) {
200 Variable* par = scope_->parameter(i); 200 Variable* par = scope_->parameter(i);
201 Slot* slot = par->slot(); 201 Slot* slot = par->slot();
202 if (slot != NULL && slot->type() == Slot::CONTEXT) { 202 if (slot != NULL && slot->type() == Slot::CONTEXT) {
203 // Save the arguments object pointer, if any. 203 // Save the arguments object pointer, if any.
204 if (arguments_object_allocated && !arguments_object_saved) { 204 if (arguments_object_allocated && !arguments_object_saved) {
205 frame_->Push(ecx); 205 frame_->EmitPush(ecx);
206 arguments_object_saved = true; 206 arguments_object_saved = true;
207 } 207 }
208 ASSERT(!scope_->is_global_scope()); // no parameters in global scope 208 ASSERT(!scope_->is_global_scope()); // no parameters in global scope
209 __ mov(eax, frame_->ParameterAt(i)); 209 __ mov(eax, frame_->ParameterAt(i));
210 // Loads ecx with context; used below in RecordWrite. 210 // Loads ecx with context; used below in RecordWrite.
211 __ mov(SlotOperand(slot, ecx), eax); 211 __ mov(SlotOperand(slot, ecx), eax);
212 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 212 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
213 __ RecordWrite(ecx, offset, eax, ebx); 213 __ RecordWrite(ecx, offset, eax, ebx);
214 } 214 }
215 } 215 }
(...skipping 17 matching lines...) Expand all
233 // If the newly-allocated arguments object is already on the 233 // If the newly-allocated arguments object is already on the
234 // stack, we make use of the convenient property that references 234 // stack, we make use of the convenient property that references
235 // representing slots take up no space on the expression stack 235 // representing slots take up no space on the expression stack
236 // (ie, it doesn't matter that the stored value is actually below 236 // (ie, it doesn't matter that the stored value is actually below
237 // the reference). 237 // the reference).
238 // 238 //
239 // If the newly-allocated argument object is not already on 239 // If the newly-allocated argument object is not already on
240 // the stack, we rely on the property that loading a 240 // the stack, we rely on the property that loading a
241 // zero-sized reference will not clobber the ecx register. 241 // zero-sized reference will not clobber the ecx register.
242 if (!arguments_object_saved) { 242 if (!arguments_object_saved) {
243 frame_->Push(ecx); 243 frame_->EmitPush(ecx);
244 } 244 }
245 arguments_ref.SetValue(NOT_CONST_INIT); 245 arguments_ref.SetValue(NOT_CONST_INIT);
246 } 246 }
247 shadow_ref.SetValue(NOT_CONST_INIT); 247 shadow_ref.SetValue(NOT_CONST_INIT);
248 } 248 }
249 frame_->Drop(); // Value is no longer needed. 249 frame_->Drop(); // Value is no longer needed.
250 } 250 }
251 251
252 // Generate code to 'execute' declarations and initialize functions 252 // Generate code to 'execute' declarations and initialize functions
253 // (source elements). In case of an illegal redeclaration we need to 253 // (source elements). In case of an illegal redeclaration we need to
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 JumpTarget true_target(this); 388 JumpTarget true_target(this);
389 JumpTarget false_target(this); 389 JumpTarget false_target(this);
390 LoadCondition(x, typeof_state, &true_target, &false_target, false); 390 LoadCondition(x, typeof_state, &true_target, &false_target, false);
391 391
392 if (has_cc()) { 392 if (has_cc()) {
393 ASSERT(frame_ != NULL); 393 ASSERT(frame_ != NULL);
394 // Convert cc_reg_ into a boolean value. 394 // Convert cc_reg_ into a boolean value.
395 JumpTarget loaded(this); 395 JumpTarget loaded(this);
396 JumpTarget materialize_true(this); 396 JumpTarget materialize_true(this);
397 materialize_true.Branch(cc_reg_); 397 materialize_true.Branch(cc_reg_);
398 frame_->Push(Immediate(Factory::false_value())); 398 frame_->EmitPush(Immediate(Factory::false_value()));
399 loaded.Jump(); 399 loaded.Jump();
400 materialize_true.Bind(); 400 materialize_true.Bind();
401 frame_->Push(Immediate(Factory::true_value())); 401 frame_->EmitPush(Immediate(Factory::true_value()));
402 loaded.Bind(); 402 loaded.Bind();
403 cc_reg_ = no_condition; 403 cc_reg_ = no_condition;
404 } 404 }
405 405
406 if (true_target.is_linked() || false_target.is_linked()) { 406 if (true_target.is_linked() || false_target.is_linked()) {
407 // We have at least one condition value that has been "translated" into 407 // We have at least one condition value that has been "translated" into
408 // a branch, thus it needs to be loaded explicitly. 408 // a branch, thus it needs to be loaded explicitly.
409 JumpTarget loaded(this); 409 JumpTarget loaded(this);
410 if (frame_ != NULL) { 410 if (frame_ != NULL) {
411 loaded.Jump(); // Don't lose the current TOS. 411 loaded.Jump(); // Don't lose the current TOS.
412 } 412 }
413 bool both = true_target.is_linked() && false_target.is_linked(); 413 bool both = true_target.is_linked() && false_target.is_linked();
414 // Load "true" if necessary. 414 // Load "true" if necessary.
415 if (true_target.is_linked()) { 415 if (true_target.is_linked()) {
416 true_target.Bind(); 416 true_target.Bind();
417 frame_->Push(Immediate(Factory::true_value())); 417 frame_->EmitPush(Immediate(Factory::true_value()));
418 } 418 }
419 // If both "true" and "false" need to be reincarnated jump across the 419 // If both "true" and "false" need to be reincarnated jump across the
420 // code for "false". 420 // code for "false".
421 if (both) { 421 if (both) {
422 loaded.Jump(); 422 loaded.Jump();
423 } 423 }
424 // Load "false" if necessary. 424 // Load "false" if necessary.
425 if (false_target.is_linked()) { 425 if (false_target.is_linked()) {
426 false_target.Bind(); 426 false_target.Bind();
427 frame_->Push(Immediate(Factory::false_value())); 427 frame_->EmitPush(Immediate(Factory::false_value()));
428 } 428 }
429 // A value is loaded on all paths reaching this point. 429 // A value is loaded on all paths reaching this point.
430 loaded.Bind(); 430 loaded.Bind();
431 } 431 }
432 ASSERT(frame_ != NULL); 432 ASSERT(frame_ != NULL);
433 ASSERT(!has_cc()); 433 ASSERT(!has_cc());
434 } 434 }
435 435
436 436
437 void CodeGenerator::LoadGlobal() { 437 void CodeGenerator::LoadGlobal() {
438 frame_->Push(GlobalObject()); 438 frame_->EmitPush(GlobalObject());
439 } 439 }
440 440
441 441
442 void CodeGenerator::LoadGlobalReceiver(Register scratch) { 442 void CodeGenerator::LoadGlobalReceiver(Register scratch) {
443 __ mov(scratch, GlobalObject()); 443 __ mov(scratch, GlobalObject());
444 frame_->Push(FieldOperand(scratch, GlobalObject::kGlobalReceiverOffset)); 444 frame_->EmitPush(FieldOperand(scratch, GlobalObject::kGlobalReceiverOffset));
445 } 445 }
446 446
447 447
448 // TODO(1241834): Get rid of this function in favor of just using Load, now 448 // TODO(1241834): Get rid of this function in favor of just using Load, now
449 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 449 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
450 // variables w/o reference errors elsewhere. 450 // variables w/o reference errors elsewhere.
451 void CodeGenerator::LoadTypeofExpression(Expression* x) { 451 void CodeGenerator::LoadTypeofExpression(Expression* x) {
452 Variable* variable = x->AsVariableProxy()->AsVariable(); 452 Variable* variable = x->AsVariableProxy()->AsVariable();
453 if (variable != NULL && !variable->is_this() && variable->is_global()) { 453 if (variable != NULL && !variable->is_this() && variable->is_global()) {
454 // NOTE: This is somewhat nasty. We force the compiler to load 454 // NOTE: This is somewhat nasty. We force the compiler to load
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 void CodeGenerator::UnloadReference(Reference* ref) { 522 void CodeGenerator::UnloadReference(Reference* ref) {
523 // Pop a reference from the stack while preserving TOS. 523 // Pop a reference from the stack while preserving TOS.
524 Comment cmnt(masm_, "[ UnloadReference"); 524 Comment cmnt(masm_, "[ UnloadReference");
525 int size = ref->size(); 525 int size = ref->size();
526 if (size == 1) { 526 if (size == 1) {
527 frame_->Pop(eax); 527 frame_->Pop(eax);
528 __ mov(frame_->Top(), eax); 528 __ mov(frame_->Top(), eax);
529 } else if (size > 1) { 529 } else if (size > 1) {
530 frame_->Pop(eax); 530 frame_->Pop(eax);
531 frame_->Drop(size); 531 frame_->Drop(size);
532 frame_->Push(eax); 532 frame_->EmitPush(eax);
533 } 533 }
534 } 534 }
535 535
536 536
537 class ToBooleanStub: public CodeStub { 537 class ToBooleanStub: public CodeStub {
538 public: 538 public:
539 ToBooleanStub() { } 539 ToBooleanStub() { }
540 540
541 void Generate(MacroAssembler* masm); 541 void Generate(MacroAssembler* masm);
542 542
(...skipping 27 matching lines...) Expand all
570 false_target->Branch(equal); 570 false_target->Branch(equal);
571 571
572 // Smi => false iff zero. 572 // Smi => false iff zero.
573 ASSERT(kSmiTag == 0); 573 ASSERT(kSmiTag == 0);
574 __ test(eax, Operand(eax)); 574 __ test(eax, Operand(eax));
575 false_target->Branch(zero); 575 false_target->Branch(zero);
576 __ test(eax, Immediate(kSmiTagMask)); 576 __ test(eax, Immediate(kSmiTagMask));
577 true_target->Branch(zero); 577 true_target->Branch(zero);
578 578
579 // Call the stub for all other cases. 579 // Call the stub for all other cases.
580 frame_->Push(eax); // Undo the pop(eax) from above. 580 frame_->EmitPush(eax); // Undo the pop(eax) from above.
581 ToBooleanStub stub; 581 ToBooleanStub stub;
582 frame_->CallStub(&stub, 1); 582 frame_->CallStub(&stub, 1);
583 // Convert the result (eax) to condition code. 583 // Convert the result (eax) to condition code.
584 __ test(eax, Operand(eax)); 584 __ test(eax, Operand(eax));
585 585
586 ASSERT(not_equal == not_zero); 586 ASSERT(not_equal == not_zero);
587 cc_reg_ = not_equal; 587 cc_reg_ = not_equal;
588 } 588 }
589 589
590 590
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 void CodeGenerator::GenericBinaryOperation(Token::Value op, 706 void CodeGenerator::GenericBinaryOperation(Token::Value op,
707 StaticType* type, 707 StaticType* type,
708 OverwriteMode overwrite_mode) { 708 OverwriteMode overwrite_mode) {
709 Comment cmnt(masm_, "[ BinaryOperation"); 709 Comment cmnt(masm_, "[ BinaryOperation");
710 Comment cmnt_token(masm_, Token::String(op)); 710 Comment cmnt_token(masm_, Token::String(op));
711 711
712 if (op == Token::COMMA) { 712 if (op == Token::COMMA) {
713 // Simply discard left value. 713 // Simply discard left value.
714 frame_->Pop(eax); 714 frame_->Pop(eax);
715 frame_->Drop(); 715 frame_->Drop();
716 frame_->Push(eax); 716 frame_->EmitPush(eax);
717 return; 717 return;
718 } 718 }
719 719
720 // Set the flags based on the operation, type and loop nesting level. 720 // Set the flags based on the operation, type and loop nesting level.
721 GenericBinaryFlags flags; 721 GenericBinaryFlags flags;
722 switch (op) { 722 switch (op) {
723 case Token::BIT_OR: 723 case Token::BIT_OR:
724 case Token::BIT_AND: 724 case Token::BIT_AND:
725 case Token::BIT_XOR: 725 case Token::BIT_XOR:
726 case Token::SHL: 726 case Token::SHL:
(...skipping 27 matching lines...) Expand all
754 // Put result back on the stack. It seems somewhat weird to let 754 // Put result back on the stack. It seems somewhat weird to let
755 // the deferred code jump back before the assignment to the frame 755 // the deferred code jump back before the assignment to the frame
756 // top, but this is just to let the peephole optimizer get rid of 756 // top, but this is just to let the peephole optimizer get rid of
757 // more code. 757 // more code.
758 __ bind(deferred->exit()); 758 __ bind(deferred->exit());
759 __ mov(frame_->Top(), eax); 759 __ mov(frame_->Top(), eax);
760 } else { 760 } else {
761 // Call the stub and push the result to the stack. 761 // Call the stub and push the result to the stack.
762 GenericBinaryOpStub stub(op, overwrite_mode, flags); 762 GenericBinaryOpStub stub(op, overwrite_mode, flags);
763 frame_->CallStub(&stub, 2); 763 frame_->CallStub(&stub, 2);
764 frame_->Push(eax); 764 frame_->EmitPush(eax);
765 } 765 }
766 } 766 }
767 767
768 768
769 class DeferredInlinedSmiOperation: public DeferredCode { 769 class DeferredInlinedSmiOperation: public DeferredCode {
770 public: 770 public:
771 DeferredInlinedSmiOperation(CodeGenerator* generator, 771 DeferredInlinedSmiOperation(CodeGenerator* generator,
772 Token::Value op, int value, 772 Token::Value op, int value,
773 OverwriteMode overwrite_mode) : 773 OverwriteMode overwrite_mode) :
774 DeferredCode(generator), op_(op), value_(value), 774 DeferredCode(generator), op_(op), value_(value),
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 } else { 937 } else {
938 deferred = new DeferredInlinedSmiAddReversed(this, int_value, 938 deferred = new DeferredInlinedSmiAddReversed(this, int_value,
939 overwrite_mode); 939 overwrite_mode);
940 } 940 }
941 frame_->Pop(eax); 941 frame_->Pop(eax);
942 __ add(Operand(eax), Immediate(value)); 942 __ add(Operand(eax), Immediate(value));
943 __ j(overflow, deferred->enter(), not_taken); 943 __ j(overflow, deferred->enter(), not_taken);
944 __ test(eax, Immediate(kSmiTagMask)); 944 __ test(eax, Immediate(kSmiTagMask));
945 __ j(not_zero, deferred->enter(), not_taken); 945 __ j(not_zero, deferred->enter(), not_taken);
946 __ bind(deferred->exit()); 946 __ bind(deferred->exit());
947 frame_->Push(eax); 947 frame_->EmitPush(eax);
948 break; 948 break;
949 } 949 }
950 950
951 case Token::SUB: { 951 case Token::SUB: {
952 DeferredCode* deferred = NULL; 952 DeferredCode* deferred = NULL;
953 frame_->Pop(eax); 953 frame_->Pop(eax);
954 if (!reversed) { 954 if (!reversed) {
955 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); 955 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode);
956 __ sub(Operand(eax), Immediate(value)); 956 __ sub(Operand(eax), Immediate(value));
957 } else { 957 } else {
958 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); 958 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode);
959 __ mov(edx, Operand(eax)); 959 __ mov(edx, Operand(eax));
960 __ mov(eax, Immediate(value)); 960 __ mov(eax, Immediate(value));
961 __ sub(eax, Operand(edx)); 961 __ sub(eax, Operand(edx));
962 } 962 }
963 __ j(overflow, deferred->enter(), not_taken); 963 __ j(overflow, deferred->enter(), not_taken);
964 __ test(eax, Immediate(kSmiTagMask)); 964 __ test(eax, Immediate(kSmiTagMask));
965 __ j(not_zero, deferred->enter(), not_taken); 965 __ j(not_zero, deferred->enter(), not_taken);
966 __ bind(deferred->exit()); 966 __ bind(deferred->exit());
967 frame_->Push(eax); 967 frame_->EmitPush(eax);
968 break; 968 break;
969 } 969 }
970 970
971 case Token::SAR: { 971 case Token::SAR: {
972 if (reversed) { 972 if (reversed) {
973 frame_->Pop(eax); 973 frame_->Pop(eax);
974 frame_->Push(Immediate(value)); 974 frame_->EmitPush(Immediate(value));
975 frame_->Push(eax); 975 frame_->EmitPush(eax);
976 GenericBinaryOperation(op, type, overwrite_mode); 976 GenericBinaryOperation(op, type, overwrite_mode);
977 } else { 977 } else {
978 int shift_value = int_value & 0x1f; // only least significant 5 bits 978 int shift_value = int_value & 0x1f; // only least significant 5 bits
979 DeferredCode* deferred = 979 DeferredCode* deferred =
980 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, 980 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value,
981 overwrite_mode); 981 overwrite_mode);
982 frame_->Pop(eax); 982 frame_->Pop(eax);
983 __ test(eax, Immediate(kSmiTagMask)); 983 __ test(eax, Immediate(kSmiTagMask));
984 __ j(not_zero, deferred->enter(), not_taken); 984 __ j(not_zero, deferred->enter(), not_taken);
985 __ sar(eax, shift_value); 985 __ sar(eax, shift_value);
986 __ and_(eax, ~kSmiTagMask); 986 __ and_(eax, ~kSmiTagMask);
987 __ bind(deferred->exit()); 987 __ bind(deferred->exit());
988 frame_->Push(eax); 988 frame_->EmitPush(eax);
989 } 989 }
990 break; 990 break;
991 } 991 }
992 992
993 case Token::SHR: { 993 case Token::SHR: {
994 if (reversed) { 994 if (reversed) {
995 frame_->Pop(eax); 995 frame_->Pop(eax);
996 frame_->Push(Immediate(value)); 996 frame_->EmitPush(Immediate(value));
997 frame_->Push(eax); 997 frame_->EmitPush(eax);
998 GenericBinaryOperation(op, type, overwrite_mode); 998 GenericBinaryOperation(op, type, overwrite_mode);
999 } else { 999 } else {
1000 int shift_value = int_value & 0x1f; // only least significant 5 bits 1000 int shift_value = int_value & 0x1f; // only least significant 5 bits
1001 DeferredCode* deferred = 1001 DeferredCode* deferred =
1002 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, 1002 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value,
1003 overwrite_mode); 1003 overwrite_mode);
1004 frame_->Pop(eax); 1004 frame_->Pop(eax);
1005 __ test(eax, Immediate(kSmiTagMask)); 1005 __ test(eax, Immediate(kSmiTagMask));
1006 __ mov(ebx, Operand(eax)); 1006 __ mov(ebx, Operand(eax));
1007 __ j(not_zero, deferred->enter(), not_taken); 1007 __ j(not_zero, deferred->enter(), not_taken);
1008 __ sar(ebx, kSmiTagSize); 1008 __ sar(ebx, kSmiTagSize);
1009 __ shr(ebx, shift_value); 1009 __ shr(ebx, shift_value);
1010 __ test(ebx, Immediate(0xc0000000)); 1010 __ test(ebx, Immediate(0xc0000000));
1011 __ j(not_zero, deferred->enter(), not_taken); 1011 __ j(not_zero, deferred->enter(), not_taken);
1012 // tag result and store it in TOS (eax) 1012 // tag result and store it in TOS (eax)
1013 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1013 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1014 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); 1014 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
1015 __ bind(deferred->exit()); 1015 __ bind(deferred->exit());
1016 frame_->Push(eax); 1016 frame_->EmitPush(eax);
1017 } 1017 }
1018 break; 1018 break;
1019 } 1019 }
1020 1020
1021 case Token::SHL: { 1021 case Token::SHL: {
1022 if (reversed) { 1022 if (reversed) {
1023 frame_->Pop(eax); 1023 frame_->Pop(eax);
1024 frame_->Push(Immediate(value)); 1024 frame_->EmitPush(Immediate(value));
1025 frame_->Push(eax); 1025 frame_->EmitPush(eax);
1026 GenericBinaryOperation(op, type, overwrite_mode); 1026 GenericBinaryOperation(op, type, overwrite_mode);
1027 } else { 1027 } else {
1028 int shift_value = int_value & 0x1f; // only least significant 5 bits 1028 int shift_value = int_value & 0x1f; // only least significant 5 bits
1029 DeferredCode* deferred = 1029 DeferredCode* deferred =
1030 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, 1030 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value,
1031 overwrite_mode); 1031 overwrite_mode);
1032 frame_->Pop(eax); 1032 frame_->Pop(eax);
1033 __ test(eax, Immediate(kSmiTagMask)); 1033 __ test(eax, Immediate(kSmiTagMask));
1034 __ mov(ebx, Operand(eax)); 1034 __ mov(ebx, Operand(eax));
1035 __ j(not_zero, deferred->enter(), not_taken); 1035 __ j(not_zero, deferred->enter(), not_taken);
1036 __ sar(ebx, kSmiTagSize); 1036 __ sar(ebx, kSmiTagSize);
1037 __ shl(ebx, shift_value); 1037 __ shl(ebx, shift_value);
1038 __ lea(ecx, Operand(ebx, 0x40000000)); 1038 __ lea(ecx, Operand(ebx, 0x40000000));
1039 __ test(ecx, Immediate(0x80000000)); 1039 __ test(ecx, Immediate(0x80000000));
1040 __ j(not_zero, deferred->enter(), not_taken); 1040 __ j(not_zero, deferred->enter(), not_taken);
1041 // tag result and store it in TOS (eax) 1041 // tag result and store it in TOS (eax)
1042 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1042 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1043 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); 1043 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
1044 __ bind(deferred->exit()); 1044 __ bind(deferred->exit());
1045 frame_->Push(eax); 1045 frame_->EmitPush(eax);
1046 } 1046 }
1047 break; 1047 break;
1048 } 1048 }
1049 1049
1050 case Token::BIT_OR: 1050 case Token::BIT_OR:
1051 case Token::BIT_XOR: 1051 case Token::BIT_XOR:
1052 case Token::BIT_AND: { 1052 case Token::BIT_AND: {
1053 DeferredCode* deferred = NULL; 1053 DeferredCode* deferred = NULL;
1054 if (!reversed) { 1054 if (!reversed) {
1055 deferred = new DeferredInlinedSmiOperation(this, op, int_value, 1055 deferred = new DeferredInlinedSmiOperation(this, op, int_value,
1056 overwrite_mode); 1056 overwrite_mode);
1057 } else { 1057 } else {
1058 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, 1058 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value,
1059 overwrite_mode); 1059 overwrite_mode);
1060 } 1060 }
1061 frame_->Pop(eax); 1061 frame_->Pop(eax);
1062 __ test(eax, Immediate(kSmiTagMask)); 1062 __ test(eax, Immediate(kSmiTagMask));
1063 __ j(not_zero, deferred->enter(), not_taken); 1063 __ j(not_zero, deferred->enter(), not_taken);
1064 if (op == Token::BIT_AND) { 1064 if (op == Token::BIT_AND) {
1065 __ and_(Operand(eax), Immediate(value)); 1065 __ and_(Operand(eax), Immediate(value));
1066 } else if (op == Token::BIT_XOR) { 1066 } else if (op == Token::BIT_XOR) {
1067 __ xor_(Operand(eax), Immediate(value)); 1067 __ xor_(Operand(eax), Immediate(value));
1068 } else { 1068 } else {
1069 ASSERT(op == Token::BIT_OR); 1069 ASSERT(op == Token::BIT_OR);
1070 __ or_(Operand(eax), Immediate(value)); 1070 __ or_(Operand(eax), Immediate(value));
1071 } 1071 }
1072 __ bind(deferred->exit()); 1072 __ bind(deferred->exit());
1073 frame_->Push(eax); 1073 frame_->EmitPush(eax);
1074 break; 1074 break;
1075 } 1075 }
1076 1076
1077 default: { 1077 default: {
1078 if (!reversed) { 1078 if (!reversed) {
1079 frame_->Push(Immediate(value)); 1079 frame_->EmitPush(Immediate(value));
1080 } else { 1080 } else {
1081 frame_->Pop(eax); 1081 frame_->Pop(eax);
1082 frame_->Push(Immediate(value)); 1082 frame_->EmitPush(Immediate(value));
1083 frame_->Push(eax); 1083 frame_->EmitPush(eax);
1084 } 1084 }
1085 GenericBinaryOperation(op, type, overwrite_mode); 1085 GenericBinaryOperation(op, type, overwrite_mode);
1086 break; 1086 break;
1087 } 1087 }
1088 } 1088 }
1089 } 1089 }
1090 1090
1091 1091
1092 class CompareStub: public CodeStub { 1092 class CompareStub: public CodeStub {
1093 public: 1093 public:
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 node->set_break_stack_height(break_stack_height_); 1286 node->set_break_stack_height(break_stack_height_);
1287 node->break_target()->set_code_generator(this); 1287 node->break_target()->set_code_generator(this);
1288 VisitStatements(node->statements()); 1288 VisitStatements(node->statements());
1289 if (node->break_target()->is_linked()) { 1289 if (node->break_target()->is_linked()) {
1290 node->break_target()->Bind(); 1290 node->break_target()->Bind();
1291 } 1291 }
1292 } 1292 }
1293 1293
1294 1294
1295 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1295 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1296 frame_->Push(Immediate(pairs)); 1296 frame_->EmitPush(Immediate(pairs));
1297 frame_->Push(esi); 1297 frame_->EmitPush(esi);
1298 frame_->Push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 1298 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
1299 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1299 frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1300 // Return value is ignored. 1300 // Return value is ignored.
1301 } 1301 }
1302 1302
1303 1303
1304 void CodeGenerator::VisitDeclaration(Declaration* node) { 1304 void CodeGenerator::VisitDeclaration(Declaration* node) {
1305 Comment cmnt(masm_, "[ Declaration"); 1305 Comment cmnt(masm_, "[ Declaration");
1306 Variable* var = node->proxy()->var(); 1306 Variable* var = node->proxy()->var();
1307 ASSERT(var != NULL); // must have been resolved 1307 ASSERT(var != NULL); // must have been resolved
1308 Slot* slot = var->slot(); 1308 Slot* slot = var->slot();
1309 1309
1310 // If it was not possible to allocate the variable at compile time, 1310 // If it was not possible to allocate the variable at compile time,
1311 // we need to "declare" it at runtime to make sure it actually 1311 // we need to "declare" it at runtime to make sure it actually
1312 // exists in the local context. 1312 // exists in the local context.
1313 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1313 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1314 // Variables with a "LOOKUP" slot were introduced as non-locals 1314 // Variables with a "LOOKUP" slot were introduced as non-locals
1315 // during variable resolution and must have mode DYNAMIC. 1315 // during variable resolution and must have mode DYNAMIC.
1316 ASSERT(var->mode() == Variable::DYNAMIC); 1316 ASSERT(var->mode() == Variable::DYNAMIC);
1317 // For now, just do a runtime call. 1317 // For now, just do a runtime call.
1318 frame_->Push(esi); 1318 frame_->EmitPush(esi);
1319 frame_->Push(Immediate(var->name())); 1319 frame_->EmitPush(Immediate(var->name()));
1320 // Declaration nodes are always introduced in one of two modes. 1320 // Declaration nodes are always introduced in one of two modes.
1321 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 1321 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
1322 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1322 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1323 frame_->Push(Immediate(Smi::FromInt(attr))); 1323 frame_->EmitPush(Immediate(Smi::FromInt(attr)));
1324 // Push initial value, if any. 1324 // Push initial value, if any.
1325 // Note: For variables we must not push an initial value (such as 1325 // Note: For variables we must not push an initial value (such as
1326 // 'undefined') because we may have a (legal) redeclaration and we 1326 // 'undefined') because we may have a (legal) redeclaration and we
1327 // must not destroy the current value. 1327 // must not destroy the current value.
1328 if (node->mode() == Variable::CONST) { 1328 if (node->mode() == Variable::CONST) {
1329 frame_->Push(Immediate(Factory::the_hole_value())); 1329 frame_->EmitPush(Immediate(Factory::the_hole_value()));
1330 } else if (node->fun() != NULL) { 1330 } else if (node->fun() != NULL) {
1331 Load(node->fun()); 1331 Load(node->fun());
1332 } else { 1332 } else {
1333 frame_->Push(Immediate(0)); // no initial value! 1333 frame_->EmitPush(Immediate(0)); // no initial value!
1334 } 1334 }
1335 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); 1335 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
1336 // Ignore the return value (declarations are statements). 1336 // Ignore the return value (declarations are statements).
1337 return; 1337 return;
1338 } 1338 }
1339 1339
1340 ASSERT(!var->is_global()); 1340 ASSERT(!var->is_global());
1341 1341
1342 // If we have a function or a constant, we need to initialize the variable. 1342 // If we have a function or a constant, we need to initialize the variable.
1343 Expression* val = NULL; 1343 Expression* val = NULL;
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1502 1502
1503 // If we're inside a try statement or the return instruction 1503 // If we're inside a try statement or the return instruction
1504 // sequence has been generated, we just jump to that 1504 // sequence has been generated, we just jump to that
1505 // point. Otherwise, we generate the return instruction sequence and 1505 // point. Otherwise, we generate the return instruction sequence and
1506 // bind the function return label. 1506 // bind the function return label.
1507 if (is_inside_try_ || function_return_.is_bound()) { 1507 if (is_inside_try_ || function_return_.is_bound()) {
1508 function_return_.Jump(); 1508 function_return_.Jump();
1509 } else { 1509 } else {
1510 function_return_.Bind(); 1510 function_return_.Bind();
1511 if (FLAG_trace) { 1511 if (FLAG_trace) {
1512 frame_->Push(eax); // undo the pop(eax) from above 1512 frame_->EmitPush(eax); // undo the pop(eax) from above
1513 frame_->CallRuntime(Runtime::kTraceExit, 1); 1513 frame_->CallRuntime(Runtime::kTraceExit, 1);
1514 } 1514 }
1515 1515
1516 // Add a label for checking the size of the code used for returning. 1516 // Add a label for checking the size of the code used for returning.
1517 Label check_exit_codesize; 1517 Label check_exit_codesize;
1518 __ bind(&check_exit_codesize); 1518 __ bind(&check_exit_codesize);
1519 1519
1520 // Leave the frame and return popping the arguments and the 1520 // Leave the frame and return popping the arguments and the
1521 // receiver. 1521 // receiver.
1522 frame_->Exit(); 1522 frame_->Exit();
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1664 default_clause = clause; 1664 default_clause = clause;
1665 continue; 1665 continue;
1666 } 1666 }
1667 1667
1668 Comment cmnt(masm_, "[ Case clause"); 1668 Comment cmnt(masm_, "[ Case clause");
1669 // Compile the test. 1669 // Compile the test.
1670 next_test.Bind(); 1670 next_test.Bind();
1671 next_test.Unuse(); 1671 next_test.Unuse();
1672 // Duplicate TOS. 1672 // Duplicate TOS.
1673 __ mov(eax, frame_->Top()); 1673 __ mov(eax, frame_->Top());
1674 frame_->Push(eax); 1674 frame_->EmitPush(eax);
1675 Load(clause->label()); 1675 Load(clause->label());
1676 Comparison(equal, true); 1676 Comparison(equal, true);
1677 Branch(false, &next_test); 1677 Branch(false, &next_test);
1678 1678
1679 // Before entering the body from the test, remove the switch value from 1679 // Before entering the body from the test, remove the switch value from
1680 // the stack. 1680 // the stack.
1681 frame_->Drop(); 1681 frame_->Drop();
1682 1682
1683 // Label the body so that fall through is enabled. 1683 // Label the body so that fall through is enabled.
1684 if (i > 0 && cases->at(i - 1)->is_default()) { 1684 if (i > 0 && cases->at(i - 1)->is_default()) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1948 // Check if enumerable is already a JSObject 1948 // Check if enumerable is already a JSObject
1949 // eax: value to be iterated over 1949 // eax: value to be iterated over
1950 __ test(eax, Immediate(kSmiTagMask)); 1950 __ test(eax, Immediate(kSmiTagMask));
1951 primitive.Branch(zero); 1951 primitive.Branch(zero);
1952 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 1952 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
1953 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 1953 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
1954 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 1954 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
1955 jsobject.Branch(above_equal); 1955 jsobject.Branch(above_equal);
1956 1956
1957 primitive.Bind(); 1957 primitive.Bind();
1958 frame_->Push(eax); 1958 frame_->EmitPush(eax);
1959 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1); 1959 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
1960 // function call returns the value in eax, which is where we want it below 1960 // function call returns the value in eax, which is where we want it below
1961 1961
1962 jsobject.Bind(); 1962 jsobject.Bind();
1963 // Get the set of properties (as a FixedArray or Map). 1963 // Get the set of properties (as a FixedArray or Map).
1964 // eax: value to be iterated over 1964 // eax: value to be iterated over
1965 frame_->Push(eax); // push the object being iterated over (slot 4) 1965 frame_->EmitPush(eax); // push the object being iterated over (slot 4)
1966 1966
1967 frame_->Push(eax); // push the Object (slot 4) for the runtime call 1967 frame_->EmitPush(eax); // push the Object (slot 4) for the runtime call
1968 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1968 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1969 1969
1970 // If we got a Map, we can do a fast modification check. 1970 // If we got a Map, we can do a fast modification check.
1971 // Otherwise, we got a FixedArray, and we have to do a slow check. 1971 // Otherwise, we got a FixedArray, and we have to do a slow check.
1972 // eax: map or fixed array (result from call to 1972 // eax: map or fixed array (result from call to
1973 // Runtime::kGetPropertyNamesFast) 1973 // Runtime::kGetPropertyNamesFast)
1974 __ mov(edx, Operand(eax)); 1974 __ mov(edx, Operand(eax));
1975 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 1975 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
1976 __ cmp(ecx, Factory::meta_map()); 1976 __ cmp(ecx, Factory::meta_map());
1977 fixed_array.Branch(not_equal); 1977 fixed_array.Branch(not_equal);
1978 1978
1979 // Get enum cache 1979 // Get enum cache
1980 // eax: map (result from call to Runtime::kGetPropertyNamesFast) 1980 // eax: map (result from call to Runtime::kGetPropertyNamesFast)
1981 __ mov(ecx, Operand(eax)); 1981 __ mov(ecx, Operand(eax));
1982 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset)); 1982 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset));
1983 // Get the bridge array held in the enumeration index field. 1983 // Get the bridge array held in the enumeration index field.
1984 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); 1984 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
1985 // Get the cache from the bridge array. 1985 // Get the cache from the bridge array.
1986 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1986 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1987 1987
1988 frame_->Push(eax); // <- slot 3 1988 frame_->EmitPush(eax); // <- slot 3
1989 frame_->Push(edx); // <- slot 2 1989 frame_->EmitPush(edx); // <- slot 2
1990 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); 1990 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
1991 __ shl(eax, kSmiTagSize); 1991 __ shl(eax, kSmiTagSize);
1992 frame_->Push(eax); // <- slot 1 1992 frame_->EmitPush(eax); // <- slot 1
1993 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0 1993 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0
1994 entry.Jump(); 1994 entry.Jump();
1995 1995
1996 fixed_array.Bind(); 1996 fixed_array.Bind();
1997 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast) 1997 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast)
1998 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 3 1998 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 3
1999 frame_->Push(eax); // <- slot 2 1999 frame_->EmitPush(eax); // <- slot 2
2000 2000
2001 // Push the length of the array and the initial index onto the stack. 2001 // Push the length of the array and the initial index onto the stack.
2002 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); 2002 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
2003 __ shl(eax, kSmiTagSize); 2003 __ shl(eax, kSmiTagSize);
2004 frame_->Push(eax); // <- slot 1 2004 frame_->EmitPush(eax); // <- slot 1
2005 frame_->Push(Immediate(Smi::FromInt(0))); // <- slot 0 2005 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0
2006 2006
2007 // Condition. 2007 // Condition.
2008 entry.Bind(); 2008 entry.Bind();
2009 __ mov(eax, frame_->ElementAt(0)); // load the current count 2009 __ mov(eax, frame_->ElementAt(0)); // load the current count
2010 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length 2010 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
2011 cleanup.Branch(above_equal); 2011 cleanup.Branch(above_equal);
2012 2012
2013 // Get the i'th entry of the array. 2013 // Get the i'th entry of the array.
2014 __ mov(edx, frame_->ElementAt(2)); 2014 __ mov(edx, frame_->ElementAt(2));
2015 __ mov(ebx, Operand(edx, eax, times_2, 2015 __ mov(ebx, Operand(edx, eax, times_2,
2016 FixedArray::kHeaderSize - kHeapObjectTag)); 2016 FixedArray::kHeaderSize - kHeapObjectTag));
2017 2017
2018 // Get the expected map from the stack or a zero map in the 2018 // Get the expected map from the stack or a zero map in the
2019 // permanent slow case eax: current iteration count ebx: i'th entry 2019 // permanent slow case eax: current iteration count ebx: i'th entry
2020 // of the enum cache 2020 // of the enum cache
2021 __ mov(edx, frame_->ElementAt(3)); 2021 __ mov(edx, frame_->ElementAt(3));
2022 // Check if the expected map still matches that of the enumerable. 2022 // Check if the expected map still matches that of the enumerable.
2023 // If not, we have to filter the key. 2023 // If not, we have to filter the key.
2024 // eax: current iteration count 2024 // eax: current iteration count
2025 // ebx: i'th entry of the enum cache 2025 // ebx: i'th entry of the enum cache
2026 // edx: expected map value 2026 // edx: expected map value
2027 __ mov(ecx, frame_->ElementAt(4)); 2027 __ mov(ecx, frame_->ElementAt(4));
2028 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); 2028 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
2029 __ cmp(ecx, Operand(edx)); 2029 __ cmp(ecx, Operand(edx));
2030 end_del_check.Branch(equal); 2030 end_del_check.Branch(equal);
2031 2031
2032 // Convert the entry to a string (or null if it isn't a property anymore). 2032 // Convert the entry to a string (or null if it isn't a property anymore).
2033 frame_->Push(frame_->ElementAt(4)); // push enumerable 2033 frame_->EmitPush(frame_->ElementAt(4)); // push enumerable
2034 frame_->Push(ebx); // push entry 2034 frame_->EmitPush(ebx); // push entry
2035 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2); 2035 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2);
2036 __ mov(ebx, Operand(eax)); 2036 __ mov(ebx, Operand(eax));
2037 2037
2038 // If the property has been removed while iterating, we just skip it. 2038 // If the property has been removed while iterating, we just skip it.
2039 __ cmp(ebx, Factory::null_value()); 2039 __ cmp(ebx, Factory::null_value());
2040 node->continue_target()->Branch(equal); 2040 node->continue_target()->Branch(equal);
2041 2041
2042 end_del_check.Bind(); 2042 end_del_check.Bind();
2043 // Store the entry in the 'each' expression and take another spin in the 2043 // Store the entry in the 'each' expression and take another spin in the
2044 // loop. edx: i'th entry of the enum cache (or string there of) 2044 // loop. edx: i'th entry of the enum cache (or string there of)
2045 frame_->Push(ebx); 2045 frame_->EmitPush(ebx);
2046 { Reference each(this, node->each()); 2046 { Reference each(this, node->each());
2047 if (!each.is_illegal()) { 2047 if (!each.is_illegal()) {
2048 if (each.size() > 0) { 2048 if (each.size() > 0) {
2049 frame_->Push(frame_->ElementAt(each.size())); 2049 frame_->EmitPush(frame_->ElementAt(each.size()));
2050 } 2050 }
2051 // If the reference was to a slot we rely on the convenient property 2051 // If the reference was to a slot we rely on the convenient property
2052 // that it doesn't matter whether a value (eg, ebx pushed above) is 2052 // that it doesn't matter whether a value (eg, ebx pushed above) is
2053 // right on top of or right underneath a zero-sized reference. 2053 // right on top of or right underneath a zero-sized reference.
2054 each.SetValue(NOT_CONST_INIT); 2054 each.SetValue(NOT_CONST_INIT);
2055 if (each.size() > 0) { 2055 if (each.size() > 0) {
2056 // It's safe to pop the value lying on top of the reference before 2056 // It's safe to pop the value lying on top of the reference before
2057 // unloading the reference itself (which preserves the top of stack, 2057 // unloading the reference itself (which preserves the top of stack,
2058 // ie, now the topmost value of the non-zero sized reference), since 2058 // ie, now the topmost value of the non-zero sized reference), since
2059 // we will discard the top of stack after unloading the reference 2059 // we will discard the top of stack after unloading the reference
2060 // anyway. 2060 // anyway.
2061 frame_->Drop(); 2061 frame_->Drop();
2062 } 2062 }
2063 } 2063 }
2064 } 2064 }
2065 // Discard the i'th entry pushed above or else the remainder of the 2065 // Discard the i'th entry pushed above or else the remainder of the
2066 // reference, whichever is currently on top of the stack. 2066 // reference, whichever is currently on top of the stack.
2067 frame_->Drop(); 2067 frame_->Drop();
2068 2068
2069 // Body. 2069 // Body.
2070 CheckStack(); // TODO(1222600): ignore if body contains calls. 2070 CheckStack(); // TODO(1222600): ignore if body contains calls.
2071 Visit(node->body()); 2071 Visit(node->body());
2072 2072
2073 // Next. 2073 // Next.
2074 node->continue_target()->Bind(); 2074 node->continue_target()->Bind();
2075 frame_->Pop(eax); 2075 frame_->Pop(eax);
2076 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 2076 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
2077 frame_->Push(eax); 2077 frame_->EmitPush(eax);
2078 entry.Jump(); 2078 entry.Jump();
2079 2079
2080 // Cleanup. 2080 // Cleanup.
2081 cleanup.Bind(); 2081 cleanup.Bind();
2082 node->break_target()->Bind(); 2082 node->break_target()->Bind();
2083 frame_->Drop(5); 2083 frame_->Drop(5);
2084 2084
2085 // Exit. 2085 // Exit.
2086 exit.Bind(); 2086 exit.Bind();
2087 2087
2088 break_stack_height_ -= kForInStackSize; 2088 break_stack_height_ -= kForInStackSize;
2089 } 2089 }
2090 2090
2091 2091
2092 void CodeGenerator::VisitTryCatch(TryCatch* node) { 2092 void CodeGenerator::VisitTryCatch(TryCatch* node) {
2093 Comment cmnt(masm_, "[ TryCatch"); 2093 Comment cmnt(masm_, "[ TryCatch");
2094 2094
2095 JumpTarget try_block(this); 2095 JumpTarget try_block(this);
2096 JumpTarget exit(this); 2096 JumpTarget exit(this);
2097 2097
2098 try_block.Call(); 2098 try_block.Call();
2099 // --- Catch block --- 2099 // --- Catch block ---
2100 frame_->Push(eax); 2100 frame_->EmitPush(eax);
2101 2101
2102 // Store the caught exception in the catch variable. 2102 // Store the caught exception in the catch variable.
2103 { Reference ref(this, node->catch_var()); 2103 { Reference ref(this, node->catch_var());
2104 ASSERT(ref.is_slot()); 2104 ASSERT(ref.is_slot());
2105 // Load the exception to the top of the stack. Here we make use of the 2105 // Load the exception to the top of the stack. Here we make use of the
2106 // convenient property that it doesn't matter whether a value is 2106 // convenient property that it doesn't matter whether a value is
2107 // immediately on top of or underneath a zero-sized reference. 2107 // immediately on top of or underneath a zero-sized reference.
2108 ref.SetValue(NOT_CONST_INIT); 2108 ref.SetValue(NOT_CONST_INIT);
2109 } 2109 }
2110 2110
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2211 // block. Should probably be extended to hold information for 2211 // block. Should probably be extended to hold information for
2212 // break/continue from within the try block. 2212 // break/continue from within the try block.
2213 enum { FALLING, THROWING, JUMPING }; 2213 enum { FALLING, THROWING, JUMPING };
2214 2214
2215 JumpTarget unlink(this); 2215 JumpTarget unlink(this);
2216 JumpTarget try_block(this); 2216 JumpTarget try_block(this);
2217 JumpTarget finally_block(this); 2217 JumpTarget finally_block(this);
2218 2218
2219 try_block.Call(); 2219 try_block.Call();
2220 2220
2221 frame_->Push(eax); 2221 frame_->EmitPush(eax);
2222 // In case of thrown exceptions, this is where we continue. 2222 // In case of thrown exceptions, this is where we continue.
2223 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); 2223 __ Set(ecx, Immediate(Smi::FromInt(THROWING)));
2224 finally_block.Jump(); 2224 finally_block.Jump();
2225 2225
2226 2226
2227 // --- Try block --- 2227 // --- Try block ---
2228 try_block.Bind(); 2228 try_block.Bind();
2229 2229
2230 frame_->PushTryHandler(TRY_FINALLY_HANDLER); 2230 frame_->PushTryHandler(TRY_FINALLY_HANDLER);
2231 int handler_height = frame_->height(); 2231 int handler_height = frame_->height();
(...skipping 26 matching lines...) Expand all
2258 int nof_unlinks = 0; 2258 int nof_unlinks = 0;
2259 for (int i = 0; i <= nof_escapes; i++) { 2259 for (int i = 0; i <= nof_escapes; i++) {
2260 shadows[i]->StopShadowing(); 2260 shadows[i]->StopShadowing();
2261 if (shadows[i]->is_linked()) nof_unlinks++; 2261 if (shadows[i]->is_linked()) nof_unlinks++;
2262 } 2262 }
2263 function_return_is_shadowed_ = function_return_was_shadowed; 2263 function_return_is_shadowed_ = function_return_was_shadowed;
2264 2264
2265 // If we can fall off the end of the try block, set the state on the stack 2265 // If we can fall off the end of the try block, set the state on the stack
2266 // to FALLING. 2266 // to FALLING.
2267 if (frame_ != NULL) { 2267 if (frame_ != NULL) {
2268 frame_->Push(Immediate(Factory::undefined_value())); // fake TOS 2268 frame_->EmitPush(Immediate(Factory::undefined_value())); // fake TOS
2269 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); 2269 __ Set(ecx, Immediate(Smi::FromInt(FALLING)));
2270 if (nof_unlinks > 0) { 2270 if (nof_unlinks > 0) {
2271 unlink.Jump(); 2271 unlink.Jump();
2272 } 2272 }
2273 } 2273 }
2274 2274
2275 // Generate code to set the state for the (formerly) shadowing targets that 2275 // Generate code to set the state for the (formerly) shadowing targets that
2276 // have been jumped to. 2276 // have been jumped to.
2277 for (int i = 0; i <= nof_escapes; i++) { 2277 for (int i = 0; i <= nof_escapes; i++) {
2278 if (shadows[i]->is_linked()) { 2278 if (shadows[i]->is_linked()) {
2279 shadows[i]->Bind(); 2279 shadows[i]->Bind();
2280 if (shadows[i]->original_target() == &function_return_) { 2280 if (shadows[i]->original_target() == &function_return_) {
2281 // If this target shadowed the function return, materialize the 2281 // If this target shadowed the function return, materialize the
2282 // return value on the stack. 2282 // return value on the stack.
2283 frame_->Push(eax); 2283 frame_->EmitPush(eax);
2284 } else { 2284 } else {
2285 // Fake TOS for targets that shadowed breaks and continues. 2285 // Fake TOS for targets that shadowed breaks and continues.
2286 frame_->Push(Immediate(Factory::undefined_value())); 2286 frame_->EmitPush(Immediate(Factory::undefined_value()));
2287 } 2287 }
2288 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); 2288 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i)));
2289 unlink.Jump(); 2289 unlink.Jump();
2290 } 2290 }
2291 } 2291 }
2292 2292
2293 // Unlink from try chain; be careful not to destroy the TOS. 2293 // Unlink from try chain; be careful not to destroy the TOS.
2294 unlink.Bind(); 2294 unlink.Bind();
2295 // Reload sp from the top handler, because some statements that we 2295 // Reload sp from the top handler, because some statements that we
2296 // break from (eg, for...in) may have left stuff on the stack. 2296 // break from (eg, for...in) may have left stuff on the stack.
2297 // Preserve the TOS in a register across stack manipulation. 2297 // Preserve the TOS in a register across stack manipulation.
2298 frame_->Pop(eax); 2298 frame_->Pop(eax);
2299 ExternalReference handler_address(Top::k_handler_address); 2299 ExternalReference handler_address(Top::k_handler_address);
2300 __ mov(edx, Operand::StaticVariable(handler_address)); 2300 __ mov(edx, Operand::StaticVariable(handler_address));
2301 const int kNextOffset = StackHandlerConstants::kNextOffset + 2301 const int kNextOffset = StackHandlerConstants::kNextOffset +
2302 StackHandlerConstants::kAddressDisplacement; 2302 StackHandlerConstants::kAddressDisplacement;
2303 __ lea(esp, Operand(edx, kNextOffset)); 2303 __ lea(esp, Operand(edx, kNextOffset));
2304 frame_->Forget(frame_->height() - handler_height); 2304 frame_->Forget(frame_->height() - handler_height);
2305 2305
2306 frame_->Pop(Operand::StaticVariable(handler_address)); 2306 frame_->Pop(Operand::StaticVariable(handler_address));
2307 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2307 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2308 // Next_sp popped. 2308 // Next_sp popped.
2309 frame_->Push(eax); 2309 frame_->EmitPush(eax);
2310 2310
2311 // --- Finally block --- 2311 // --- Finally block ---
2312 finally_block.Bind(); 2312 finally_block.Bind();
2313 2313
2314 // Push the state on the stack. 2314 // Push the state on the stack.
2315 frame_->Push(ecx); 2315 frame_->EmitPush(ecx);
2316 2316
2317 // We keep two elements on the stack - the (possibly faked) result 2317 // We keep two elements on the stack - the (possibly faked) result
2318 // and the state - while evaluating the finally block. Record it, so 2318 // and the state - while evaluating the finally block. Record it, so
2319 // that a break/continue crossing this statement can restore the 2319 // that a break/continue crossing this statement can restore the
2320 // stack. 2320 // stack.
2321 const int kFinallyStackSize = 2 * kPointerSize; 2321 const int kFinallyStackSize = 2 * kPointerSize;
2322 break_stack_height_ += kFinallyStackSize; 2322 break_stack_height_ += kFinallyStackSize;
2323 2323
2324 // Generate code for the statements in the finally block. 2324 // Generate code for the statements in the finally block.
2325 VisitStatements(node->finally_block()->statements()); 2325 VisitStatements(node->finally_block()->statements());
(...skipping 12 matching lines...) Expand all
2338 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); 2338 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
2339 shadows[i]->original_target()->Branch(equal); 2339 shadows[i]->original_target()->Branch(equal);
2340 } 2340 }
2341 } 2341 }
2342 2342
2343 // Check if we need to rethrow the exception. 2343 // Check if we need to rethrow the exception.
2344 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); 2344 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
2345 exit.Branch(not_equal); 2345 exit.Branch(not_equal);
2346 2346
2347 // Rethrow exception. 2347 // Rethrow exception.
2348 frame_->Push(eax); // undo pop from above 2348 frame_->EmitPush(eax); // undo pop from above
2349 frame_->CallRuntime(Runtime::kReThrow, 1); 2349 frame_->CallRuntime(Runtime::kReThrow, 1);
2350 2350
2351 // Done. 2351 // Done.
2352 exit.Bind(); 2352 exit.Bind();
2353 } 2353 }
2354 } 2354 }
2355 2355
2356 2356
2357 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2357 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2358 Comment cmnt(masm_, "[ DebuggerStatement"); 2358 Comment cmnt(masm_, "[ DebuggerStatement");
2359 RecordStatementPosition(node); 2359 RecordStatementPosition(node);
2360 frame_->CallRuntime(Runtime::kDebugBreak, 0); 2360 frame_->CallRuntime(Runtime::kDebugBreak, 0);
2361 // Ignore the return value. 2361 // Ignore the return value.
2362 } 2362 }
2363 2363
2364 2364
2365 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 2365 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
2366 ASSERT(boilerplate->IsBoilerplate()); 2366 ASSERT(boilerplate->IsBoilerplate());
2367 2367
2368 // Push the boilerplate on the stack. 2368 // Push the boilerplate on the stack.
2369 frame_->Push(Immediate(boilerplate)); 2369 frame_->EmitPush(Immediate(boilerplate));
2370 2370
2371 // Create a new closure. 2371 // Create a new closure.
2372 frame_->Push(esi); 2372 frame_->EmitPush(esi);
2373 frame_->CallRuntime(Runtime::kNewClosure, 2); 2373 frame_->CallRuntime(Runtime::kNewClosure, 2);
2374 frame_->Push(eax); 2374 frame_->EmitPush(eax);
2375 } 2375 }
2376 2376
2377 2377
2378 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2378 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2379 Comment cmnt(masm_, "[ FunctionLiteral"); 2379 Comment cmnt(masm_, "[ FunctionLiteral");
2380 2380
2381 // Build the function boilerplate and instantiate it. 2381 // Build the function boilerplate and instantiate it.
2382 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 2382 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
2383 // Check for stack-overflow exception. 2383 // Check for stack-overflow exception.
2384 if (HasStackOverflow()) return; 2384 if (HasStackOverflow()) return;
(...skipping 28 matching lines...) Expand all
2413 } 2413 }
2414 exit.Bind(); 2414 exit.Bind();
2415 } 2415 }
2416 2416
2417 2417
2418 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2418 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2419 if (slot->type() == Slot::LOOKUP) { 2419 if (slot->type() == Slot::LOOKUP) {
2420 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2420 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2421 2421
2422 // For now, just do a runtime call. 2422 // For now, just do a runtime call.
2423 frame_->Push(esi); 2423 frame_->EmitPush(esi);
2424 frame_->Push(Immediate(slot->var()->name())); 2424 frame_->EmitPush(Immediate(slot->var()->name()));
2425 2425
2426 if (typeof_state == INSIDE_TYPEOF) { 2426 if (typeof_state == INSIDE_TYPEOF) {
2427 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2427 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2428 } else { 2428 } else {
2429 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2429 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2430 } 2430 }
2431 frame_->Push(eax); 2431 frame_->EmitPush(eax);
2432 2432
2433 } else { 2433 } else {
2434 // Note: We would like to keep the assert below, but it fires because of 2434 // Note: We would like to keep the assert below, but it fires because of
2435 // some nasty code in LoadTypeofExpression() which should be removed... 2435 // some nasty code in LoadTypeofExpression() which should be removed...
2436 // ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2436 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2437 if (slot->var()->mode() == Variable::CONST) { 2437 if (slot->var()->mode() == Variable::CONST) {
2438 // Const slots may contain 'the hole' value (the constant hasn't been 2438 // Const slots may contain 'the hole' value (the constant hasn't been
2439 // initialized yet) which needs to be converted into the 'undefined' 2439 // initialized yet) which needs to be converted into the 'undefined'
2440 // value. 2440 // value.
2441 Comment cmnt(masm_, "[ Load const"); 2441 Comment cmnt(masm_, "[ Load const");
2442 JumpTarget exit(this); 2442 JumpTarget exit(this);
2443 __ mov(eax, SlotOperand(slot, ecx)); 2443 __ mov(eax, SlotOperand(slot, ecx));
2444 __ cmp(eax, Factory::the_hole_value()); 2444 __ cmp(eax, Factory::the_hole_value());
2445 exit.Branch(not_equal); 2445 exit.Branch(not_equal);
2446 __ mov(eax, Factory::undefined_value()); 2446 __ mov(eax, Factory::undefined_value());
2447 exit.Bind(); 2447 exit.Bind();
2448 frame_->Push(eax); 2448 frame_->EmitPush(eax);
2449 } else { 2449 } else {
2450 frame_->Push(SlotOperand(slot, ecx)); 2450 frame_->EmitPush(SlotOperand(slot, ecx));
2451 } 2451 }
2452 } 2452 }
2453 } 2453 }
2454 2454
2455 2455
2456 void CodeGenerator::VisitSlot(Slot* node) { 2456 void CodeGenerator::VisitSlot(Slot* node) {
2457 Comment cmnt(masm_, "[ Slot"); 2457 Comment cmnt(masm_, "[ Slot");
2458 LoadFromSlot(node, typeof_state()); 2458 LoadFromSlot(node, typeof_state());
2459 } 2459 }
2460 2460
(...skipping 21 matching lines...) Expand all
2482 2482
2483 2483
2484 void CodeGenerator::VisitLiteral(Literal* node) { 2484 void CodeGenerator::VisitLiteral(Literal* node) {
2485 Comment cmnt(masm_, "[ Literal"); 2485 Comment cmnt(masm_, "[ Literal");
2486 if (node->handle()->IsSmi() && !IsInlineSmi(node)) { 2486 if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
2487 // To prevent long attacker-controlled byte sequences in code, larger 2487 // To prevent long attacker-controlled byte sequences in code, larger
2488 // Smis are loaded in two steps. 2488 // Smis are loaded in two steps.
2489 int bits = reinterpret_cast<int>(*node->handle()); 2489 int bits = reinterpret_cast<int>(*node->handle());
2490 __ mov(eax, bits & 0x0000FFFF); 2490 __ mov(eax, bits & 0x0000FFFF);
2491 __ xor_(eax, bits & 0xFFFF0000); 2491 __ xor_(eax, bits & 0xFFFF0000);
2492 frame_->Push(eax); 2492 frame_->EmitPush(eax);
2493 } else { 2493 } else {
2494 frame_->Push(Immediate(node->handle())); 2494 frame_->EmitPush(Immediate(node->handle()));
2495 } 2495 }
2496 } 2496 }
2497 2497
2498 2498
2499 class RegExpDeferred: public DeferredCode { 2499 class RegExpDeferred: public DeferredCode {
2500 public: 2500 public:
2501 RegExpDeferred(CodeGenerator* generator, RegExpLiteral* node) 2501 RegExpDeferred(CodeGenerator* generator, RegExpLiteral* node)
2502 : DeferredCode(generator), node_(node) { 2502 : DeferredCode(generator), node_(node) {
2503 set_comment("[ RegExpDeferred"); 2503 set_comment("[ RegExpDeferred");
2504 } 2504 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2542 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2542 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2543 __ mov(ebx, FieldOperand(ecx, literal_offset)); 2543 __ mov(ebx, FieldOperand(ecx, literal_offset));
2544 2544
2545 // Check whether we need to materialize the RegExp object. 2545 // Check whether we need to materialize the RegExp object.
2546 // If so, jump to the deferred code. 2546 // If so, jump to the deferred code.
2547 __ cmp(ebx, Factory::undefined_value()); 2547 __ cmp(ebx, Factory::undefined_value());
2548 __ j(equal, deferred->enter(), not_taken); 2548 __ j(equal, deferred->enter(), not_taken);
2549 __ bind(deferred->exit()); 2549 __ bind(deferred->exit());
2550 2550
2551 // Push the literal. 2551 // Push the literal.
2552 frame_->Push(ebx); 2552 frame_->EmitPush(ebx);
2553 } 2553 }
2554 2554
2555 2555
2556 // This deferred code stub will be used for creating the boilerplate 2556 // This deferred code stub will be used for creating the boilerplate
2557 // by calling Runtime_CreateObjectLiteral. 2557 // by calling Runtime_CreateObjectLiteral.
2558 // Each created boilerplate is stored in the JSFunction and they are 2558 // Each created boilerplate is stored in the JSFunction and they are
2559 // therefore context dependent. 2559 // therefore context dependent.
2560 class ObjectLiteralDeferred: public DeferredCode { 2560 class ObjectLiteralDeferred: public DeferredCode {
2561 public: 2561 public:
2562 ObjectLiteralDeferred(CodeGenerator* generator, 2562 ObjectLiteralDeferred(CodeGenerator* generator,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2602 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2602 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2603 __ mov(ebx, FieldOperand(ecx, literal_offset)); 2603 __ mov(ebx, FieldOperand(ecx, literal_offset));
2604 2604
2605 // Check whether we need to materialize the object literal boilerplate. 2605 // Check whether we need to materialize the object literal boilerplate.
2606 // If so, jump to the deferred code. 2606 // If so, jump to the deferred code.
2607 __ cmp(ebx, Factory::undefined_value()); 2607 __ cmp(ebx, Factory::undefined_value());
2608 __ j(equal, deferred->enter(), not_taken); 2608 __ j(equal, deferred->enter(), not_taken);
2609 __ bind(deferred->exit()); 2609 __ bind(deferred->exit());
2610 2610
2611 // Push the literal. 2611 // Push the literal.
2612 frame_->Push(ebx); 2612 frame_->EmitPush(ebx);
2613 // Clone the boilerplate object. 2613 // Clone the boilerplate object.
2614 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); 2614 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
2615 // Push the new cloned literal object as the result. 2615 // Push the new cloned literal object as the result.
2616 frame_->Push(eax); 2616 frame_->EmitPush(eax);
2617 2617
2618 2618
2619 for (int i = 0; i < node->properties()->length(); i++) { 2619 for (int i = 0; i < node->properties()->length(); i++) {
2620 ObjectLiteral::Property* property = node->properties()->at(i); 2620 ObjectLiteral::Property* property = node->properties()->at(i);
2621 switch (property->kind()) { 2621 switch (property->kind()) {
2622 case ObjectLiteral::Property::CONSTANT: break; 2622 case ObjectLiteral::Property::CONSTANT: break;
2623 case ObjectLiteral::Property::COMPUTED: { 2623 case ObjectLiteral::Property::COMPUTED: {
2624 Handle<Object> key(property->key()->handle()); 2624 Handle<Object> key(property->key()->handle());
2625 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2625 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2626 if (key->IsSymbol()) { 2626 if (key->IsSymbol()) {
2627 __ mov(eax, frame_->Top()); 2627 __ mov(eax, frame_->Top());
2628 frame_->Push(eax); 2628 frame_->EmitPush(eax);
2629 Load(property->value()); 2629 Load(property->value());
2630 frame_->Pop(eax); 2630 frame_->Pop(eax);
2631 __ Set(ecx, Immediate(key)); 2631 __ Set(ecx, Immediate(key));
2632 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 2632 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
2633 frame_->Drop(); 2633 frame_->Drop();
2634 // Ignore result. 2634 // Ignore result.
2635 break; 2635 break;
2636 } 2636 }
2637 // Fall through 2637 // Fall through
2638 } 2638 }
2639 case ObjectLiteral::Property::PROTOTYPE: { 2639 case ObjectLiteral::Property::PROTOTYPE: {
2640 __ mov(eax, frame_->Top()); 2640 __ mov(eax, frame_->Top());
2641 frame_->Push(eax); 2641 frame_->EmitPush(eax);
2642 Load(property->key()); 2642 Load(property->key());
2643 Load(property->value()); 2643 Load(property->value());
2644 frame_->CallRuntime(Runtime::kSetProperty, 3); 2644 frame_->CallRuntime(Runtime::kSetProperty, 3);
2645 // Ignore result. 2645 // Ignore result.
2646 break; 2646 break;
2647 } 2647 }
2648 case ObjectLiteral::Property::SETTER: { 2648 case ObjectLiteral::Property::SETTER: {
2649 // Duplicate the resulting object on the stack. The runtime 2649 // Duplicate the resulting object on the stack. The runtime
2650 // function will pop the three arguments passed in. 2650 // function will pop the three arguments passed in.
2651 __ mov(eax, frame_->Top()); 2651 __ mov(eax, frame_->Top());
2652 frame_->Push(eax); 2652 frame_->EmitPush(eax);
2653 Load(property->key()); 2653 Load(property->key());
2654 frame_->Push(Immediate(Smi::FromInt(1))); 2654 frame_->EmitPush(Immediate(Smi::FromInt(1)));
2655 Load(property->value()); 2655 Load(property->value());
2656 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2656 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2657 // Ignore result. 2657 // Ignore result.
2658 break; 2658 break;
2659 } 2659 }
2660 case ObjectLiteral::Property::GETTER: { 2660 case ObjectLiteral::Property::GETTER: {
2661 // Duplicate the resulting object on the stack. The runtime 2661 // Duplicate the resulting object on the stack. The runtime
2662 // function will pop the three arguments passed in. 2662 // function will pop the three arguments passed in.
2663 __ mov(eax, frame_->Top()); 2663 __ mov(eax, frame_->Top());
2664 frame_->Push(eax); 2664 frame_->EmitPush(eax);
2665 Load(property->key()); 2665 Load(property->key());
2666 frame_->Push(Immediate(Smi::FromInt(0))); 2666 frame_->EmitPush(Immediate(Smi::FromInt(0)));
2667 Load(property->value()); 2667 Load(property->value());
2668 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2668 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2669 // Ignore result. 2669 // Ignore result.
2670 break; 2670 break;
2671 } 2671 }
2672 default: UNREACHABLE(); 2672 default: UNREACHABLE();
2673 } 2673 }
2674 } 2674 }
2675 } 2675 }
2676 2676
2677 2677
2678 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2678 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2679 Comment cmnt(masm_, "[ ArrayLiteral"); 2679 Comment cmnt(masm_, "[ ArrayLiteral");
2680 2680
2681 // Call runtime to create the array literal. 2681 // Call runtime to create the array literal.
2682 frame_->Push(Immediate(node->literals())); 2682 frame_->EmitPush(Immediate(node->literals()));
2683 // Load the function of this frame. 2683 // Load the function of this frame.
2684 __ mov(ecx, frame_->Function()); 2684 __ mov(ecx, frame_->Function());
2685 // Load the literals array of the function. 2685 // Load the literals array of the function.
2686 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2686 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2687 frame_->Push(ecx); 2687 frame_->EmitPush(ecx);
2688 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2); 2688 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2);
2689 2689
2690 // Push the resulting array literal on the stack. 2690 // Push the resulting array literal on the stack.
2691 frame_->Push(eax); 2691 frame_->EmitPush(eax);
2692 2692
2693 // Generate code to set the elements in the array that are not 2693 // Generate code to set the elements in the array that are not
2694 // literals. 2694 // literals.
2695 for (int i = 0; i < node->values()->length(); i++) { 2695 for (int i = 0; i < node->values()->length(); i++) {
2696 Expression* value = node->values()->at(i); 2696 Expression* value = node->values()->at(i);
2697 2697
2698 // If value is literal the property value is already 2698 // If value is literal the property value is already
2699 // set in the boilerplate object. 2699 // set in the boilerplate object.
2700 if (value->AsLiteral() == NULL) { 2700 if (value->AsLiteral() == NULL) {
2701 // The property must be set by generated code. 2701 // The property must be set by generated code.
(...skipping 25 matching lines...) Expand all
2727 2727
2728 2728
2729 void CodeGenerator::VisitAssignment(Assignment* node) { 2729 void CodeGenerator::VisitAssignment(Assignment* node) {
2730 Comment cmnt(masm_, "[ Assignment"); 2730 Comment cmnt(masm_, "[ Assignment");
2731 2731
2732 RecordStatementPosition(node); 2732 RecordStatementPosition(node);
2733 { Reference target(this, node->target()); 2733 { Reference target(this, node->target());
2734 if (target.is_illegal()) { 2734 if (target.is_illegal()) {
2735 // Fool the virtual frame into thinking that we left the assignment's 2735 // Fool the virtual frame into thinking that we left the assignment's
2736 // value on the frame. 2736 // value on the frame.
2737 frame_->Push(Immediate(Smi::FromInt(0))); 2737 frame_->EmitPush(Immediate(Smi::FromInt(0)));
2738 return; 2738 return;
2739 } 2739 }
2740 2740
2741 if (node->op() == Token::ASSIGN || 2741 if (node->op() == Token::ASSIGN ||
2742 node->op() == Token::INIT_VAR || 2742 node->op() == Token::INIT_VAR ||
2743 node->op() == Token::INIT_CONST) { 2743 node->op() == Token::INIT_CONST) {
2744 Load(node->value()); 2744 Load(node->value());
2745 2745
2746 } else { 2746 } else {
2747 target.GetValue(NOT_INSIDE_TYPEOF); 2747 target.GetValue(NOT_INSIDE_TYPEOF);
(...skipping 26 matching lines...) Expand all
2774 } 2774 }
2775 } 2775 }
2776 2776
2777 2777
2778 void CodeGenerator::VisitThrow(Throw* node) { 2778 void CodeGenerator::VisitThrow(Throw* node) {
2779 Comment cmnt(masm_, "[ Throw"); 2779 Comment cmnt(masm_, "[ Throw");
2780 2780
2781 Load(node->exception()); 2781 Load(node->exception());
2782 __ RecordPosition(node->position()); 2782 __ RecordPosition(node->position());
2783 frame_->CallRuntime(Runtime::kThrow, 1); 2783 frame_->CallRuntime(Runtime::kThrow, 1);
2784 frame_->Push(eax); 2784 frame_->EmitPush(eax);
2785 } 2785 }
2786 2786
2787 2787
2788 void CodeGenerator::VisitProperty(Property* node) { 2788 void CodeGenerator::VisitProperty(Property* node) {
2789 Comment cmnt(masm_, "[ Property"); 2789 Comment cmnt(masm_, "[ Property");
2790 Reference property(this, node); 2790 Reference property(this, node);
2791 property.GetValue(typeof_state()); 2791 property.GetValue(typeof_state());
2792 } 2792 }
2793 2793
2794 2794
(...skipping 17 matching lines...) Expand all
2812 // automatically handles this by loading the arguments before the function 2812 // automatically handles this by loading the arguments before the function
2813 // is resolved in cache misses (this also holds for megamorphic calls). 2813 // is resolved in cache misses (this also holds for megamorphic calls).
2814 // ------------------------------------------------------------------------ 2814 // ------------------------------------------------------------------------
2815 2815
2816 if (var != NULL && !var->is_this() && var->is_global()) { 2816 if (var != NULL && !var->is_this() && var->is_global()) {
2817 // ---------------------------------- 2817 // ----------------------------------
2818 // JavaScript example: 'foo(1, 2, 3)' // foo is global 2818 // JavaScript example: 'foo(1, 2, 3)' // foo is global
2819 // ---------------------------------- 2819 // ----------------------------------
2820 2820
2821 // Push the name of the function and the receiver onto the stack. 2821 // Push the name of the function and the receiver onto the stack.
2822 frame_->Push(Immediate(var->name())); 2822 frame_->EmitPush(Immediate(var->name()));
2823 2823
2824 // Pass the global object as the receiver and let the IC stub 2824 // Pass the global object as the receiver and let the IC stub
2825 // patch the stack to use the global proxy as 'this' in the 2825 // patch the stack to use the global proxy as 'this' in the
2826 // invoked function. 2826 // invoked function.
2827 LoadGlobal(); 2827 LoadGlobal();
2828 2828
2829 // Load the arguments. 2829 // Load the arguments.
2830 int arg_count = args->length(); 2830 int arg_count = args->length();
2831 for (int i = 0; i < arg_count; i++) { 2831 for (int i = 0; i < arg_count; i++) {
2832 Load(args->at(i)); 2832 Load(args->at(i));
2833 } 2833 }
2834 2834
2835 // Setup the receiver register and call the IC initialization code. 2835 // Setup the receiver register and call the IC initialization code.
2836 Handle<Code> stub = ComputeCallInitialize(arg_count); 2836 Handle<Code> stub = ComputeCallInitialize(arg_count);
2837 __ RecordPosition(node->position()); 2837 __ RecordPosition(node->position());
2838 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, 2838 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
2839 arg_count + 1); 2839 arg_count + 1);
2840 __ mov(esi, frame_->Context()); 2840 __ mov(esi, frame_->Context());
2841 2841
2842 // Overwrite the function on the stack with the result. 2842 // Overwrite the function on the stack with the result.
2843 __ mov(frame_->Top(), eax); 2843 __ mov(frame_->Top(), eax);
2844 2844
2845 } else if (var != NULL && var->slot() != NULL && 2845 } else if (var != NULL && var->slot() != NULL &&
2846 var->slot()->type() == Slot::LOOKUP) { 2846 var->slot()->type() == Slot::LOOKUP) {
2847 // ---------------------------------- 2847 // ----------------------------------
2848 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 2848 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
2849 // ---------------------------------- 2849 // ----------------------------------
2850 2850
2851 // Load the function 2851 // Load the function
2852 frame_->Push(esi); 2852 frame_->EmitPush(esi);
2853 frame_->Push(Immediate(var->name())); 2853 frame_->EmitPush(Immediate(var->name()));
2854 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2854 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2855 // eax: slot value; edx: receiver 2855 // eax: slot value; edx: receiver
2856 2856
2857 // Load the receiver. 2857 // Load the receiver.
2858 frame_->Push(eax); 2858 frame_->EmitPush(eax);
2859 frame_->Push(edx); 2859 frame_->EmitPush(edx);
2860 2860
2861 // Call the function. 2861 // Call the function.
2862 CallWithArguments(args, node->position()); 2862 CallWithArguments(args, node->position());
2863 2863
2864 } else if (property != NULL) { 2864 } else if (property != NULL) {
2865 // Check if the key is a literal string. 2865 // Check if the key is a literal string.
2866 Literal* literal = property->key()->AsLiteral(); 2866 Literal* literal = property->key()->AsLiteral();
2867 2867
2868 if (literal != NULL && literal->handle()->IsSymbol()) { 2868 if (literal != NULL && literal->handle()->IsSymbol()) {
2869 // ------------------------------------------------------------------ 2869 // ------------------------------------------------------------------
2870 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2870 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2871 // ------------------------------------------------------------------ 2871 // ------------------------------------------------------------------
2872 2872
2873 // Push the name of the function and the receiver onto the stack. 2873 // Push the name of the function and the receiver onto the stack.
2874 frame_->Push(Immediate(literal->handle())); 2874 frame_->EmitPush(Immediate(literal->handle()));
2875 Load(property->obj()); 2875 Load(property->obj());
2876 2876
2877 // Load the arguments. 2877 // Load the arguments.
2878 int arg_count = args->length(); 2878 int arg_count = args->length();
2879 for (int i = 0; i < arg_count; i++) { 2879 for (int i = 0; i < arg_count; i++) {
2880 Load(args->at(i)); 2880 Load(args->at(i));
2881 } 2881 }
2882 2882
2883 // Call the IC initialization code. 2883 // Call the IC initialization code.
2884 Handle<Code> stub = ComputeCallInitialize(arg_count); 2884 Handle<Code> stub = ComputeCallInitialize(arg_count);
2885 __ RecordPosition(node->position()); 2885 __ RecordPosition(node->position());
2886 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 2886 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
2887 __ mov(esi, frame_->Context()); 2887 __ mov(esi, frame_->Context());
2888 2888
2889 // Overwrite the function on the stack with the result. 2889 // Overwrite the function on the stack with the result.
2890 __ mov(frame_->Top(), eax); 2890 __ mov(frame_->Top(), eax);
2891 2891
2892 } else { 2892 } else {
2893 // ------------------------------------------- 2893 // -------------------------------------------
2894 // JavaScript example: 'array[index](1, 2, 3)' 2894 // JavaScript example: 'array[index](1, 2, 3)'
2895 // ------------------------------------------- 2895 // -------------------------------------------
2896 2896
2897 // Load the function to call from the property through a reference. 2897 // Load the function to call from the property through a reference.
2898 Reference ref(this, property); 2898 Reference ref(this, property);
2899 ref.GetValue(NOT_INSIDE_TYPEOF); 2899 ref.GetValue(NOT_INSIDE_TYPEOF);
2900 2900
2901 // Pass receiver to called function. 2901 // Pass receiver to called function.
2902 // The reference's size is non-negative. 2902 // The reference's size is non-negative.
2903 frame_->Push(frame_->ElementAt(ref.size())); 2903 frame_->EmitPush(frame_->ElementAt(ref.size()));
2904 2904
2905 // Call the function. 2905 // Call the function.
2906 CallWithArguments(args, node->position()); 2906 CallWithArguments(args, node->position());
2907 } 2907 }
2908 2908
2909 } else { 2909 } else {
2910 // ---------------------------------- 2910 // ----------------------------------
2911 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2911 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2912 // ---------------------------------- 2912 // ----------------------------------
2913 2913
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
3061 got_char_code.Jump(); 3061 got_char_code.Jump();
3062 3062
3063 // ASCII string. 3063 // ASCII string.
3064 ascii_string.Bind(); 3064 ascii_string.Bind();
3065 // Load the byte. 3065 // Load the byte.
3066 __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); 3066 __ movzx_b(eax, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize));
3067 3067
3068 got_char_code.Bind(); 3068 got_char_code.Bind();
3069 ASSERT(kSmiTag == 0); 3069 ASSERT(kSmiTag == 0);
3070 __ shl(eax, kSmiTagSize); 3070 __ shl(eax, kSmiTagSize);
3071 frame_->Push(eax); 3071 frame_->EmitPush(eax);
3072 end.Jump(); 3072 end.Jump();
3073 3073
3074 // Handle non-flat strings. 3074 // Handle non-flat strings.
3075 not_a_flat_string.Bind(); 3075 not_a_flat_string.Bind();
3076 __ and_(edi, kStringRepresentationMask); 3076 __ and_(edi, kStringRepresentationMask);
3077 __ cmp(edi, kConsStringTag); 3077 __ cmp(edi, kConsStringTag);
3078 not_a_cons_string_either.Branch(not_equal, not_taken); 3078 not_a_cons_string_either.Branch(not_equal, not_taken);
3079 3079
3080 // ConsString. 3080 // ConsString.
3081 // Get the first of the two strings. 3081 // Get the first of the two strings.
3082 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset)); 3082 __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
3083 try_again_with_new_string.Jump(); 3083 try_again_with_new_string.Jump();
3084 3084
3085 not_a_cons_string_either.Bind(); 3085 not_a_cons_string_either.Bind();
3086 __ cmp(edi, kSlicedStringTag); 3086 __ cmp(edi, kSlicedStringTag);
3087 slow_case.Branch(not_equal, not_taken); 3087 slow_case.Branch(not_equal, not_taken);
3088 3088
3089 // SlicedString. 3089 // SlicedString.
3090 // Add the offset to the index. 3090 // Add the offset to the index.
3091 __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset)); 3091 __ add(ebx, FieldOperand(eax, SlicedString::kStartOffset));
3092 slow_case.Branch(overflow); 3092 slow_case.Branch(overflow);
3093 // Get the underlying string. 3093 // Get the underlying string.
3094 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset)); 3094 __ mov(eax, FieldOperand(eax, SlicedString::kBufferOffset));
3095 try_again_with_new_string.Jump(); 3095 try_again_with_new_string.Jump();
3096 3096
3097 slow_case.Bind(); 3097 slow_case.Bind();
3098 frame_->Push(Immediate(Factory::undefined_value())); 3098 frame_->EmitPush(Immediate(Factory::undefined_value()));
3099 3099
3100 end.Bind(); 3100 end.Bind();
3101 } 3101 }
3102 3102
3103 3103
3104 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3104 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3105 ASSERT(args->length() == 1); 3105 ASSERT(args->length() == 1);
3106 Load(args->at(0)); 3106 Load(args->at(0));
3107 JumpTarget answer(this); 3107 JumpTarget answer(this);
3108 // We need the CC bits to come out as not_equal in the case where the 3108 // We need the CC bits to come out as not_equal in the case where the
(...skipping 19 matching lines...) Expand all
3128 ASSERT(args->length() == 0); 3128 ASSERT(args->length() == 0);
3129 3129
3130 // Seed the result with the formal parameters count, which will be 3130 // Seed the result with the formal parameters count, which will be
3131 // used in case no arguments adaptor frame is found below the 3131 // used in case no arguments adaptor frame is found below the
3132 // current frame. 3132 // current frame.
3133 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 3133 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
3134 3134
3135 // Call the shared stub to get to the arguments.length. 3135 // Call the shared stub to get to the arguments.length.
3136 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 3136 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
3137 frame_->CallStub(&stub, 0); 3137 frame_->CallStub(&stub, 0);
3138 frame_->Push(eax); 3138 frame_->EmitPush(eax);
3139 } 3139 }
3140 3140
3141 3141
3142 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3142 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3143 ASSERT(args->length() == 1); 3143 ASSERT(args->length() == 1);
3144 JumpTarget leave(this); 3144 JumpTarget leave(this);
3145 Load(args->at(0)); // Load the object. 3145 Load(args->at(0)); // Load the object.
3146 __ mov(eax, frame_->Top()); 3146 __ mov(eax, frame_->Top());
3147 // if (object->IsSmi()) return object. 3147 // if (object->IsSmi()) return object.
3148 __ test(eax, Immediate(kSmiTagMask)); 3148 __ test(eax, Immediate(kSmiTagMask));
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3219 if (CheckForInlineRuntimeCall(node)) { 3219 if (CheckForInlineRuntimeCall(node)) {
3220 return; 3220 return;
3221 } 3221 }
3222 3222
3223 ZoneList<Expression*>* args = node->arguments(); 3223 ZoneList<Expression*>* args = node->arguments();
3224 Comment cmnt(masm_, "[ CallRuntime"); 3224 Comment cmnt(masm_, "[ CallRuntime");
3225 Runtime::Function* function = node->function(); 3225 Runtime::Function* function = node->function();
3226 3226
3227 if (function == NULL) { 3227 if (function == NULL) {
3228 // Prepare stack for calling JS runtime function. 3228 // Prepare stack for calling JS runtime function.
3229 frame_->Push(Immediate(node->name())); 3229 frame_->EmitPush(Immediate(node->name()));
3230 // Push the builtins object found in the current global object. 3230 // Push the builtins object found in the current global object.
3231 __ mov(edx, GlobalObject()); 3231 __ mov(edx, GlobalObject());
3232 frame_->Push(FieldOperand(edx, GlobalObject::kBuiltinsOffset)); 3232 frame_->EmitPush(FieldOperand(edx, GlobalObject::kBuiltinsOffset));
3233 } 3233 }
3234 3234
3235 // Push the arguments ("left-to-right"). 3235 // Push the arguments ("left-to-right").
3236 int arg_count = args->length(); 3236 int arg_count = args->length();
3237 for (int i = 0; i < arg_count; i++) { 3237 for (int i = 0; i < arg_count; i++) {
3238 Load(args->at(i)); 3238 Load(args->at(i));
3239 } 3239 }
3240 3240
3241 if (function == NULL) { 3241 if (function == NULL) {
3242 // Call the JS runtime function. 3242 // Call the JS runtime function.
3243 Handle<Code> stub = ComputeCallInitialize(arg_count); 3243 Handle<Code> stub = ComputeCallInitialize(arg_count);
3244 __ Set(eax, Immediate(args->length())); 3244 __ Set(eax, Immediate(args->length()));
3245 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 3245 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
3246 __ mov(esi, frame_->Context()); 3246 __ mov(esi, frame_->Context());
3247 __ mov(frame_->Top(), eax); 3247 __ mov(frame_->Top(), eax);
3248 } else { 3248 } else {
3249 // Call the C runtime function. 3249 // Call the C runtime function.
3250 frame_->CallRuntime(function, arg_count); 3250 frame_->CallRuntime(function, arg_count);
3251 frame_->Push(eax); 3251 frame_->EmitPush(eax);
3252 } 3252 }
3253 } 3253 }
3254 3254
3255 3255
3256 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 3256 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
3257 // Note that because of NOT and an optimization in comparison of a typeof 3257 // Note that because of NOT and an optimization in comparison of a typeof
3258 // expression to a literal string, this function can fail to leave a value 3258 // expression to a literal string, this function can fail to leave a value
3259 // on top of the frame or in the cc register. 3259 // on top of the frame or in the cc register.
3260 Comment cmnt(masm_, "[ UnaryOperation"); 3260 Comment cmnt(masm_, "[ UnaryOperation");
3261 3261
3262 Token::Value op = node->op(); 3262 Token::Value op = node->op();
3263 3263
3264 if (op == Token::NOT) { 3264 if (op == Token::NOT) {
3265 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, 3265 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
3266 false_target(), true_target(), true); 3266 false_target(), true_target(), true);
3267 cc_reg_ = NegateCondition(cc_reg_); 3267 cc_reg_ = NegateCondition(cc_reg_);
3268 3268
3269 } else if (op == Token::DELETE) { 3269 } else if (op == Token::DELETE) {
3270 Property* property = node->expression()->AsProperty(); 3270 Property* property = node->expression()->AsProperty();
3271 if (property != NULL) { 3271 if (property != NULL) {
3272 Load(property->obj()); 3272 Load(property->obj());
3273 Load(property->key()); 3273 Load(property->key());
3274 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 3274 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
3275 frame_->Push(eax); 3275 frame_->EmitPush(eax);
3276 return; 3276 return;
3277 } 3277 }
3278 3278
3279 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 3279 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
3280 if (variable != NULL) { 3280 if (variable != NULL) {
3281 Slot* slot = variable->slot(); 3281 Slot* slot = variable->slot();
3282 if (variable->is_global()) { 3282 if (variable->is_global()) {
3283 LoadGlobal(); 3283 LoadGlobal();
3284 frame_->Push(Immediate(variable->name())); 3284 frame_->EmitPush(Immediate(variable->name()));
3285 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 3285 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
3286 frame_->Push(eax); 3286 frame_->EmitPush(eax);
3287 return; 3287 return;
3288 3288
3289 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 3289 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
3290 // lookup the context holding the named variable 3290 // lookup the context holding the named variable
3291 frame_->Push(esi); 3291 frame_->EmitPush(esi);
3292 frame_->Push(Immediate(variable->name())); 3292 frame_->EmitPush(Immediate(variable->name()));
3293 frame_->CallRuntime(Runtime::kLookupContext, 2); 3293 frame_->CallRuntime(Runtime::kLookupContext, 2);
3294 // eax: context 3294 // eax: context
3295 frame_->Push(eax); 3295 frame_->EmitPush(eax);
3296 frame_->Push(Immediate(variable->name())); 3296 frame_->EmitPush(Immediate(variable->name()));
3297 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 3297 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
3298 frame_->Push(eax); 3298 frame_->EmitPush(eax);
3299 return; 3299 return;
3300 } 3300 }
3301 3301
3302 // Default: Result of deleting non-global, not dynamically 3302 // Default: Result of deleting non-global, not dynamically
3303 // introduced variables is false. 3303 // introduced variables is false.
3304 frame_->Push(Immediate(Factory::false_value())); 3304 frame_->EmitPush(Immediate(Factory::false_value()));
3305 3305
3306 } else { 3306 } else {
3307 // Default: Result of deleting expressions is true. 3307 // Default: Result of deleting expressions is true.
3308 Load(node->expression()); // may have side-effects 3308 Load(node->expression()); // may have side-effects
3309 __ Set(frame_->Top(), Immediate(Factory::true_value())); 3309 __ Set(frame_->Top(), Immediate(Factory::true_value()));
3310 } 3310 }
3311 3311
3312 } else if (op == Token::TYPEOF) { 3312 } else if (op == Token::TYPEOF) {
3313 // Special case for loading the typeof expression; see comment on 3313 // Special case for loading the typeof expression; see comment on
3314 // LoadTypeofExpression(). 3314 // LoadTypeofExpression().
3315 LoadTypeofExpression(node->expression()); 3315 LoadTypeofExpression(node->expression());
3316 frame_->CallRuntime(Runtime::kTypeof, 1); 3316 frame_->CallRuntime(Runtime::kTypeof, 1);
3317 frame_->Push(eax); 3317 frame_->EmitPush(eax);
3318 3318
3319 } else { 3319 } else {
3320 Load(node->expression()); 3320 Load(node->expression());
3321 switch (op) { 3321 switch (op) {
3322 case Token::NOT: 3322 case Token::NOT:
3323 case Token::DELETE: 3323 case Token::DELETE:
3324 case Token::TYPEOF: 3324 case Token::TYPEOF:
3325 UNREACHABLE(); // handled above 3325 UNREACHABLE(); // handled above
3326 break; 3326 break;
3327 3327
3328 case Token::SUB: { 3328 case Token::SUB: {
3329 UnarySubStub stub; 3329 UnarySubStub stub;
3330 // TODO(1222589): remove dependency of TOS being cached inside stub 3330 // TODO(1222589): remove dependency of TOS being cached inside stub
3331 frame_->Pop(eax); 3331 frame_->Pop(eax);
3332 frame_->CallStub(&stub, 0); 3332 frame_->CallStub(&stub, 0);
3333 frame_->Push(eax); 3333 frame_->EmitPush(eax);
3334 break; 3334 break;
3335 } 3335 }
3336 3336
3337 case Token::BIT_NOT: { 3337 case Token::BIT_NOT: {
3338 // Smi check. 3338 // Smi check.
3339 JumpTarget smi_label(this); 3339 JumpTarget smi_label(this);
3340 JumpTarget continue_label(this); 3340 JumpTarget continue_label(this);
3341 frame_->Pop(eax); 3341 frame_->Pop(eax);
3342 __ test(eax, Immediate(kSmiTagMask)); 3342 __ test(eax, Immediate(kSmiTagMask));
3343 smi_label.Branch(zero, taken); 3343 smi_label.Branch(zero, taken);
3344 3344
3345 frame_->Push(eax); // undo popping of TOS 3345 frame_->EmitPush(eax); // undo popping of TOS
3346 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_FUNCTION, 1); 3346 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_FUNCTION, 1);
3347 3347
3348 continue_label.Jump(); 3348 continue_label.Jump();
3349 smi_label.Bind(); 3349 smi_label.Bind();
3350 __ not_(eax); 3350 __ not_(eax);
3351 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag. 3351 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag.
3352 continue_label.Bind(); 3352 continue_label.Bind();
3353 frame_->Push(eax); 3353 frame_->EmitPush(eax);
3354 break; 3354 break;
3355 } 3355 }
3356 3356
3357 case Token::VOID: 3357 case Token::VOID:
3358 __ mov(frame_->Top(), Factory::undefined_value()); 3358 __ mov(frame_->Top(), Factory::undefined_value());
3359 break; 3359 break;
3360 3360
3361 case Token::ADD: { 3361 case Token::ADD: {
3362 // Smi check. 3362 // Smi check.
3363 JumpTarget continue_label(this); 3363 JumpTarget continue_label(this);
3364 frame_->Pop(eax); 3364 frame_->Pop(eax);
3365 __ test(eax, Immediate(kSmiTagMask)); 3365 __ test(eax, Immediate(kSmiTagMask));
3366 continue_label.Branch(zero); 3366 continue_label.Branch(zero);
3367 3367
3368 frame_->Push(eax); 3368 frame_->EmitPush(eax);
3369 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1); 3369 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1);
3370 3370
3371 continue_label.Bind(); 3371 continue_label.Bind();
3372 frame_->Push(eax); 3372 frame_->EmitPush(eax);
3373 break; 3373 break;
3374 } 3374 }
3375 3375
3376 default: 3376 default:
3377 UNREACHABLE(); 3377 UNREACHABLE();
3378 } 3378 }
3379 } 3379 }
3380 } 3380 }
3381 3381
3382 3382
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3469 Comment cmnt(masm_, "[ CountOperation"); 3469 Comment cmnt(masm_, "[ CountOperation");
3470 3470
3471 bool is_postfix = node->is_postfix(); 3471 bool is_postfix = node->is_postfix();
3472 bool is_increment = node->op() == Token::INC; 3472 bool is_increment = node->op() == Token::INC;
3473 3473
3474 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 3474 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3475 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3475 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3476 3476
3477 // Postfix: Make room for the result. 3477 // Postfix: Make room for the result.
3478 if (is_postfix) { 3478 if (is_postfix) {
3479 frame_->Push(Immediate(0)); 3479 frame_->EmitPush(Immediate(0));
3480 } 3480 }
3481 3481
3482 { Reference target(this, node->expression()); 3482 { Reference target(this, node->expression());
3483 if (target.is_illegal()) { 3483 if (target.is_illegal()) {
3484 // Spoof the virtual frame to have the expected height (one higher 3484 // Spoof the virtual frame to have the expected height (one higher
3485 // than on entry). 3485 // than on entry).
3486 if (!is_postfix) { 3486 if (!is_postfix) {
3487 frame_->Push(Immediate(Smi::FromInt(0))); 3487 frame_->EmitPush(Immediate(Smi::FromInt(0)));
3488 } 3488 }
3489 return; 3489 return;
3490 } 3490 }
3491 target.GetValue(NOT_INSIDE_TYPEOF); 3491 target.GetValue(NOT_INSIDE_TYPEOF);
3492 3492
3493 CountOperationDeferred* deferred = 3493 CountOperationDeferred* deferred =
3494 new CountOperationDeferred(this, is_postfix, is_increment, 3494 new CountOperationDeferred(this, is_postfix, is_increment,
3495 target.size() * kPointerSize); 3495 target.size() * kPointerSize);
3496 3496
3497 frame_->Pop(eax); // Load TOS into eax for calculations below 3497 frame_->Pop(eax); // Load TOS into eax for calculations below
(...skipping 12 matching lines...) Expand all
3510 3510
3511 // If the count operation didn't overflow and the result is a 3511 // If the count operation didn't overflow and the result is a
3512 // valid smi, we're done. Otherwise, we jump to the deferred 3512 // valid smi, we're done. Otherwise, we jump to the deferred
3513 // slow-case code. 3513 // slow-case code.
3514 __ j(overflow, deferred->enter(), not_taken); 3514 __ j(overflow, deferred->enter(), not_taken);
3515 __ test(eax, Immediate(kSmiTagMask)); 3515 __ test(eax, Immediate(kSmiTagMask));
3516 __ j(not_zero, deferred->enter(), not_taken); 3516 __ j(not_zero, deferred->enter(), not_taken);
3517 3517
3518 // Store the new value in the target if not const. 3518 // Store the new value in the target if not const.
3519 __ bind(deferred->exit()); 3519 __ bind(deferred->exit());
3520 frame_->Push(eax); // Push the new value to TOS 3520 frame_->EmitPush(eax); // Push the new value to TOS
3521 if (!is_const) target.SetValue(NOT_CONST_INIT); 3521 if (!is_const) target.SetValue(NOT_CONST_INIT);
3522 } 3522 }
3523 3523
3524 // Postfix: Discard the new value and use the old. 3524 // Postfix: Discard the new value and use the old.
3525 if (is_postfix) { 3525 if (is_postfix) {
3526 frame_->Drop(); 3526 frame_->Drop();
3527 } 3527 }
3528 } 3528 }
3529 3529
3530 3530
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3567 // We have a materialized value on the frame. 3567 // We have a materialized value on the frame.
3568 JumpTarget pop_and_continue(this); 3568 JumpTarget pop_and_continue(this);
3569 JumpTarget exit(this); 3569 JumpTarget exit(this);
3570 3570
3571 // Avoid popping the result if it converts to 'false' using the 3571 // Avoid popping the result if it converts to 'false' using the
3572 // standard ToBoolean() conversion as described in ECMA-262, section 3572 // standard ToBoolean() conversion as described in ECMA-262, section
3573 // 9.2, page 30. 3573 // 9.2, page 30.
3574 // 3574 //
3575 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3575 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3576 __ mov(eax, frame_->Top()); 3576 __ mov(eax, frame_->Top());
3577 frame_->Push(eax); 3577 frame_->EmitPush(eax);
3578 ToBoolean(&pop_and_continue, &exit); 3578 ToBoolean(&pop_and_continue, &exit);
3579 Branch(false, &exit); 3579 Branch(false, &exit);
3580 3580
3581 // Pop the result of evaluating the first part. 3581 // Pop the result of evaluating the first part.
3582 pop_and_continue.Bind(); 3582 pop_and_continue.Bind();
3583 frame_->Drop(); 3583 frame_->Drop();
3584 3584
3585 // Evaluate right side expression. 3585 // Evaluate right side expression.
3586 is_true.Bind(); 3586 is_true.Bind();
3587 Load(node->right()); 3587 Load(node->right());
(...skipping 22 matching lines...) Expand all
3610 } else { 3610 } else {
3611 // We have a materialized value on the frame. 3611 // We have a materialized value on the frame.
3612 JumpTarget pop_and_continue(this); 3612 JumpTarget pop_and_continue(this);
3613 JumpTarget exit(this); 3613 JumpTarget exit(this);
3614 3614
3615 // Avoid popping the result if it converts to 'true' using the 3615 // Avoid popping the result if it converts to 'true' using the
3616 // standard ToBoolean() conversion as described in ECMA-262, 3616 // standard ToBoolean() conversion as described in ECMA-262,
3617 // section 9.2, page 30. 3617 // section 9.2, page 30.
3618 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3618 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3619 __ mov(eax, frame_->Top()); 3619 __ mov(eax, frame_->Top());
3620 frame_->Push(eax); 3620 frame_->EmitPush(eax);
3621 ToBoolean(&exit, &pop_and_continue); 3621 ToBoolean(&exit, &pop_and_continue);
3622 Branch(true, &exit); 3622 Branch(true, &exit);
3623 3623
3624 // Pop the result of evaluating the first part. 3624 // Pop the result of evaluating the first part.
3625 pop_and_continue.Bind(); 3625 pop_and_continue.Bind();
3626 frame_->Drop(); 3626 frame_->Drop();
3627 3627
3628 // Evaluate right side expression. 3628 // Evaluate right side expression.
3629 is_false.Bind(); 3629 is_false.Bind();
3630 Load(node->right()); 3630 Load(node->right());
(...skipping 30 matching lines...) Expand all
3661 } else { 3661 } else {
3662 Load(node->left()); 3662 Load(node->left());
3663 Load(node->right()); 3663 Load(node->right());
3664 GenericBinaryOperation(node->op(), node->type(), overwrite_mode); 3664 GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
3665 } 3665 }
3666 } 3666 }
3667 } 3667 }
3668 3668
3669 3669
3670 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3670 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3671 frame_->Push(frame_->Function()); 3671 frame_->EmitPush(frame_->Function());
3672 } 3672 }
3673 3673
3674 3674
3675 class InstanceofStub: public CodeStub { 3675 class InstanceofStub: public CodeStub {
3676 public: 3676 public:
3677 InstanceofStub() { } 3677 InstanceofStub() { }
3678 3678
3679 void Generate(MacroAssembler* masm); 3679 void Generate(MacroAssembler* masm);
3680 3680
3681 private: 3681 private:
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
3844 case Token::LTE: 3844 case Token::LTE:
3845 cc = less_equal; 3845 cc = less_equal;
3846 break; 3846 break;
3847 case Token::GTE: 3847 case Token::GTE:
3848 cc = greater_equal; 3848 cc = greater_equal;
3849 break; 3849 break;
3850 case Token::IN: { 3850 case Token::IN: {
3851 Load(left); 3851 Load(left);
3852 Load(right); 3852 Load(right);
3853 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); 3853 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
3854 frame_->Push(eax); // push the result 3854 frame_->EmitPush(eax); // push the result
3855 return; 3855 return;
3856 } 3856 }
3857 case Token::INSTANCEOF: { 3857 case Token::INSTANCEOF: {
3858 Load(left); 3858 Load(left);
3859 Load(right); 3859 Load(right);
3860 InstanceofStub stub; 3860 InstanceofStub stub;
3861 frame_->CallStub(&stub, 2); 3861 frame_->CallStub(&stub, 2);
3862 __ test(eax, Operand(eax)); 3862 __ test(eax, Operand(eax));
3863 cc_reg_ = zero; 3863 cc_reg_ = zero;
3864 return; 3864 return;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
3949 // Setup the name register. 3949 // Setup the name register.
3950 __ mov(ecx, name); 3950 __ mov(ecx, name);
3951 3951
3952 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3952 Variable* var = expression_->AsVariableProxy()->AsVariable();
3953 if (var != NULL) { 3953 if (var != NULL) {
3954 ASSERT(var->is_global()); 3954 ASSERT(var->is_global());
3955 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 3955 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
3956 } else { 3956 } else {
3957 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3957 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3958 } 3958 }
3959 frame->Push(eax); // IC call leaves result in eax, push it out 3959 frame->EmitPush(eax); // IC call leaves result in eax, push it out
3960 break; 3960 break;
3961 } 3961 }
3962 3962
3963 case KEYED: { 3963 case KEYED: {
3964 // TODO(1241834): Make sure that this it is safe to ignore the 3964 // TODO(1241834): Make sure that this it is safe to ignore the
3965 // distinction between expressions in a typeof and not in a typeof. 3965 // distinction between expressions in a typeof and not in a typeof.
3966 Comment cmnt(masm, "[ Load from keyed Property"); 3966 Comment cmnt(masm, "[ Load from keyed Property");
3967 Property* property = expression_->AsProperty(); 3967 Property* property = expression_->AsProperty();
3968 ASSERT(property != NULL); 3968 ASSERT(property != NULL);
3969 __ RecordPosition(property->position()); 3969 __ RecordPosition(property->position());
3970 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 3970 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3971 3971
3972 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3972 Variable* var = expression_->AsVariableProxy()->AsVariable();
3973 if (var != NULL) { 3973 if (var != NULL) {
3974 ASSERT(var->is_global()); 3974 ASSERT(var->is_global());
3975 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 3975 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
3976 } else { 3976 } else {
3977 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3977 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3978 } 3978 }
3979 frame->Push(eax); // IC call leaves result in eax, push it out 3979 frame->EmitPush(eax); // IC call leaves result in eax, push it out
3980 break; 3980 break;
3981 } 3981 }
3982 3982
3983 default: 3983 default:
3984 UNREACHABLE(); 3984 UNREACHABLE();
3985 } 3985 }
3986 } 3986 }
3987 3987
3988 3988
3989 void Reference::SetValue(InitState init_state) { 3989 void Reference::SetValue(InitState init_state) {
3990 ASSERT(!is_illegal()); 3990 ASSERT(!is_illegal());
3991 ASSERT(!cgen_->has_cc()); 3991 ASSERT(!cgen_->has_cc());
3992 MacroAssembler* masm = cgen_->masm(); 3992 MacroAssembler* masm = cgen_->masm();
3993 VirtualFrame* frame = cgen_->frame(); 3993 VirtualFrame* frame = cgen_->frame();
3994 switch (type_) { 3994 switch (type_) {
3995 case SLOT: { 3995 case SLOT: {
3996 Comment cmnt(masm, "[ Store to Slot"); 3996 Comment cmnt(masm, "[ Store to Slot");
3997 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3997 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3998 ASSERT(slot != NULL); 3998 ASSERT(slot != NULL);
3999 if (slot->type() == Slot::LOOKUP) { 3999 if (slot->type() == Slot::LOOKUP) {
4000 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 4000 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
4001 4001
4002 // For now, just do a runtime call. 4002 // For now, just do a runtime call.
4003 frame->Push(esi); 4003 frame->EmitPush(esi);
4004 frame->Push(Immediate(slot->var()->name())); 4004 frame->EmitPush(Immediate(slot->var()->name()));
4005 4005
4006 if (init_state == CONST_INIT) { 4006 if (init_state == CONST_INIT) {
4007 // Same as the case for a normal store, but ignores attribute 4007 // Same as the case for a normal store, but ignores attribute
4008 // (e.g. READ_ONLY) of context slot so that we can initialize 4008 // (e.g. READ_ONLY) of context slot so that we can initialize
4009 // const properties (introduced via eval("const foo = (some 4009 // const properties (introduced via eval("const foo = (some
4010 // expr);")). Also, uses the current function context instead of 4010 // expr);")). Also, uses the current function context instead of
4011 // the top context. 4011 // the top context.
4012 // 4012 //
4013 // Note that we must declare the foo upon entry of eval(), via a 4013 // Note that we must declare the foo upon entry of eval(), via a
4014 // context slot declaration, but we cannot initialize it at the 4014 // context slot declaration, but we cannot initialize it at the
4015 // same time, because the const declaration may be at the end of 4015 // same time, because the const declaration may be at the end of
4016 // the eval code (sigh...) and the const variable may have been 4016 // the eval code (sigh...) and the const variable may have been
4017 // used before (where its value is 'undefined'). Thus, we can only 4017 // used before (where its value is 'undefined'). Thus, we can only
4018 // do the initialization when we actually encounter the expression 4018 // do the initialization when we actually encounter the expression
4019 // and when the expression operands are defined and valid, and 4019 // and when the expression operands are defined and valid, and
4020 // thus we need the split into 2 operations: declaration of the 4020 // thus we need the split into 2 operations: declaration of the
4021 // context slot followed by initialization. 4021 // context slot followed by initialization.
4022 frame->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 4022 frame->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
4023 } else { 4023 } else {
4024 frame->CallRuntime(Runtime::kStoreContextSlot, 3); 4024 frame->CallRuntime(Runtime::kStoreContextSlot, 3);
4025 } 4025 }
4026 // Storing a variable must keep the (new) value on the expression 4026 // Storing a variable must keep the (new) value on the expression
4027 // stack. This is necessary for compiling chained assignment 4027 // stack. This is necessary for compiling chained assignment
4028 // expressions. 4028 // expressions.
4029 frame->Push(eax); 4029 frame->EmitPush(eax);
4030 4030
4031 } else { 4031 } else {
4032 ASSERT(slot->var()->mode() != Variable::DYNAMIC); 4032 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
4033 4033
4034 JumpTarget exit(cgen_); 4034 JumpTarget exit(cgen_);
4035 if (init_state == CONST_INIT) { 4035 if (init_state == CONST_INIT) {
4036 ASSERT(slot->var()->mode() == Variable::CONST); 4036 ASSERT(slot->var()->mode() == Variable::CONST);
4037 // Only the first const initialization must be executed (the slot 4037 // Only the first const initialization must be executed (the slot
4038 // still contains 'the hole' value). When the assignment is 4038 // still contains 'the hole' value). When the assignment is
4039 // executed, the code is identical to a normal store (see below). 4039 // executed, the code is identical to a normal store (see below).
4040 Comment cmnt(masm, "[ Init const"); 4040 Comment cmnt(masm, "[ Init const");
4041 __ mov(eax, cgen_->SlotOperand(slot, ecx)); 4041 __ mov(eax, cgen_->SlotOperand(slot, ecx));
4042 __ cmp(eax, Factory::the_hole_value()); 4042 __ cmp(eax, Factory::the_hole_value());
4043 exit.Branch(not_equal); 4043 exit.Branch(not_equal);
4044 } 4044 }
4045 4045
4046 // We must execute the store. Storing a variable must keep the 4046 // We must execute the store. Storing a variable must keep the
4047 // (new) value on the stack. This is necessary for compiling 4047 // (new) value on the stack. This is necessary for compiling
4048 // assignment expressions. 4048 // assignment expressions.
4049 // 4049 //
4050 // Note: We will reach here even with slot->var()->mode() == 4050 // Note: We will reach here even with slot->var()->mode() ==
4051 // Variable::CONST because of const declarations which will 4051 // Variable::CONST because of const declarations which will
4052 // initialize consts to 'the hole' value and by doing so, end up 4052 // initialize consts to 'the hole' value and by doing so, end up
4053 // calling this code. 4053 // calling this code.
4054 frame->Pop(eax); 4054 frame->Pop(eax);
4055 __ mov(cgen_->SlotOperand(slot, ecx), eax); 4055 __ mov(cgen_->SlotOperand(slot, ecx), eax);
4056 frame->Push(eax); // RecordWrite may destroy the value in eax. 4056 frame->EmitPush(eax); // RecordWrite may destroy the value in eax.
4057 if (slot->type() == Slot::CONTEXT) { 4057 if (slot->type() == Slot::CONTEXT) {
4058 // ecx is loaded with context when calling SlotOperand above. 4058 // ecx is loaded with context when calling SlotOperand above.
4059 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 4059 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
4060 __ RecordWrite(ecx, offset, eax, ebx); 4060 __ RecordWrite(ecx, offset, eax, ebx);
4061 } 4061 }
4062 // If we definitely did not jump over the assignment, we do not need 4062 // If we definitely did not jump over the assignment, we do not need
4063 // to bind the exit label. Doing so can defeat peephole 4063 // to bind the exit label. Doing so can defeat peephole
4064 // optimization. 4064 // optimization.
4065 if (init_state == CONST_INIT) { 4065 if (init_state == CONST_INIT) {
4066 exit.Bind(); 4066 exit.Bind();
4067 } 4067 }
4068 } 4068 }
4069 break; 4069 break;
4070 } 4070 }
4071 4071
4072 case NAMED: { 4072 case NAMED: {
4073 Comment cmnt(masm, "[ Store to named Property"); 4073 Comment cmnt(masm, "[ Store to named Property");
4074 // Call the appropriate IC code. 4074 // Call the appropriate IC code.
4075 Handle<String> name(GetName()); 4075 Handle<String> name(GetName());
4076 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 4076 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
4077 // TODO(1222589): Make the IC grab the values from the stack. 4077 // TODO(1222589): Make the IC grab the values from the stack.
4078 frame->Pop(eax); 4078 frame->Pop(eax);
4079 // Setup the name register. 4079 // Setup the name register.
4080 __ mov(ecx, name); 4080 __ mov(ecx, name);
4081 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4081 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4082 frame->Push(eax); // IC call leaves result in eax, push it out 4082 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4083 break; 4083 break;
4084 } 4084 }
4085 4085
4086 case KEYED: { 4086 case KEYED: {
4087 Comment cmnt(masm, "[ Store to keyed Property"); 4087 Comment cmnt(masm, "[ Store to keyed Property");
4088 Property* property = expression_->AsProperty(); 4088 Property* property = expression_->AsProperty();
4089 ASSERT(property != NULL); 4089 ASSERT(property != NULL);
4090 __ RecordPosition(property->position()); 4090 __ RecordPosition(property->position());
4091 // Call IC code. 4091 // Call IC code.
4092 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 4092 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
4093 // TODO(1222589): Make the IC grab the values from the stack. 4093 // TODO(1222589): Make the IC grab the values from the stack.
4094 frame->Pop(eax); 4094 frame->Pop(eax);
4095 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4095 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4096 frame->Push(eax); // IC call leaves result in eax, push it out 4096 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4097 break; 4097 break;
4098 } 4098 }
4099 4099
4100 default: 4100 default:
4101 UNREACHABLE(); 4101 UNREACHABLE();
4102 } 4102 }
4103 } 4103 }
4104 4104
4105 4105
4106 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). 4106 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
(...skipping 1214 matching lines...) Expand 10 before | Expand all | Expand 10 after
5321 5321
5322 // Slow-case: Go through the JavaScript implementation. 5322 // Slow-case: Go through the JavaScript implementation.
5323 __ bind(&slow); 5323 __ bind(&slow);
5324 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5324 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5325 } 5325 }
5326 5326
5327 5327
5328 #undef __ 5328 #undef __
5329 5329
5330 } } // namespace v8::internal 5330 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « v8/src/codegen-arm.cc ('k') | v8/src/virtual-frame-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698