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

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

Issue 11232: First step toward allowing constants to appear in the virtual frame... (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 | « no previous file | src/jump-target-ia32.cc » ('j') | src/virtual-frame-ia32.h » ('J')
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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 frame_->EmitPush(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 frame_->SpillAll();
161 Comment cmnt(masm_, "[ allocate local context"); 162 Comment cmnt(masm_, "[ allocate local context");
162 // Save the arguments object pointer, if any. 163 // Save the arguments object pointer, if any.
163 if (arguments_object_allocated && !arguments_object_saved) { 164 if (arguments_object_allocated && !arguments_object_saved) {
164 frame_->EmitPush(ecx); 165 frame_->EmitPush(ecx);
165 arguments_object_saved = true; 166 arguments_object_saved = true;
166 } 167 }
167 // Allocate local context. 168 // Allocate local context.
168 // Get outer context and create a new context based on it. 169 // Get outer context and create a new context based on it.
169 frame_->EmitPush(frame_->Function()); 170 frame_->EmitPush(frame_->Function());
170 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result 171 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result
(...skipping 22 matching lines...) Expand all
193 // needs to be copied into the context, it must be the last argument 194 // needs to be copied into the context, it must be the last argument
194 // passed to the parameter that needs to be copied. This is a rare 195 // passed to the parameter that needs to be copied. This is a rare
195 // case so we don't check for it, instead we rely on the copying 196 // 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 197 // order: such a parameter is copied repeatedly into the same
197 // context location and thus the last value is what is seen inside 198 // context location and thus the last value is what is seen inside
198 // the function. 199 // the function.
199 for (int i = 0; i < scope_->num_parameters(); i++) { 200 for (int i = 0; i < scope_->num_parameters(); i++) {
200 Variable* par = scope_->parameter(i); 201 Variable* par = scope_->parameter(i);
201 Slot* slot = par->slot(); 202 Slot* slot = par->slot();
202 if (slot != NULL && slot->type() == Slot::CONTEXT) { 203 if (slot != NULL && slot->type() == Slot::CONTEXT) {
203 // Save the arguments object pointer, if any.
William Hesse 2008/11/18 16:37:34 What is this change?
Kevin Millikin (Chromium) 2008/11/18 19:12:06 As far as I can tell, the only reason to save ecx
204 if (arguments_object_allocated && !arguments_object_saved) {
205 frame_->EmitPush(ecx);
206 arguments_object_saved = true;
207 }
208 ASSERT(!scope_->is_global_scope()); // no parameters in global scope 204 ASSERT(!scope_->is_global_scope()); // no parameters in global scope
209 __ mov(eax, frame_->ParameterAt(i)); 205 __ mov(eax, frame_->ParameterAt(i));
210 // Loads ecx with context; used below in RecordWrite. 206 // Loads ecx with context; used below in RecordWrite.
211 __ mov(SlotOperand(slot, ecx), eax); 207 __ mov(SlotOperand(slot, edx), eax);
212 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 208 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
213 __ RecordWrite(ecx, offset, eax, ebx); 209 __ RecordWrite(edx, offset, eax, ebx);
214 } 210 }
215 } 211 }
216 } 212 }
217 213
218 // This section stores the pointer to the arguments object that 214 // This section stores the pointer to the arguments object that
219 // was allocated and copied into above. If the address was not 215 // was allocated and copied into above. If the address was not
220 // saved to TOS, we push ecx onto the stack. 216 // saved to TOS, we push ecx onto the stack.
221 // 217 //
222 // Store the arguments object. This must happen after context 218 // Store the arguments object. This must happen after context
223 // initialization because the arguments object may be stored in the 219 // initialization because the arguments object may be stored in the
224 // context. 220 // context.
225 if (arguments_object_allocated) { 221 if (arguments_object_allocated) {
226 ASSERT(scope_->arguments() != NULL); 222 ASSERT(scope_->arguments() != NULL);
227 ASSERT(scope_->arguments_shadow() != NULL); 223 ASSERT(scope_->arguments_shadow() != NULL);
228 Comment cmnt(masm_, "[ store arguments object"); 224 Comment cmnt(masm_, "[ store arguments object");
229 { Reference shadow_ref(this, scope_->arguments_shadow()); 225 { Reference shadow_ref(this, scope_->arguments_shadow());
230 ASSERT(shadow_ref.is_slot()); 226 ASSERT(shadow_ref.is_slot());
231 { Reference arguments_ref(this, scope_->arguments()); 227 { Reference arguments_ref(this, scope_->arguments());
232 ASSERT(arguments_ref.is_slot()); 228 ASSERT(arguments_ref.is_slot());
233 // If the newly-allocated arguments object is already on the 229 // If the newly-allocated arguments object is already on the
234 // stack, we make use of the convenient property that references 230 // stack, we make use of the convenient property that references
235 // representing slots take up no space on the expression stack 231 // representing slots take up no space on the expression stack
236 // (ie, it doesn't matter that the stored value is actually below 232 // (ie, it doesn't matter that the stored value is actually below
237 // the reference). 233 // the reference).
238 // 234 //
239 // If the newly-allocated argument object is not already on 235 // If the newly-allocated argument object is not already on
240 // the stack, we rely on the property that loading a 236 // the stack, we rely on the property that loading a
241 // zero-sized reference will not clobber the ecx register. 237 // zero-sized reference will not clobber the ecx register.
242 if (!arguments_object_saved) { 238 if (!arguments_object_saved) {
239 frame_->SpillAll();
243 frame_->EmitPush(ecx); 240 frame_->EmitPush(ecx);
244 } 241 }
245 arguments_ref.SetValue(NOT_CONST_INIT); 242 arguments_ref.SetValue(NOT_CONST_INIT);
246 } 243 }
247 shadow_ref.SetValue(NOT_CONST_INIT); 244 shadow_ref.SetValue(NOT_CONST_INIT);
248 } 245 }
249 frame_->Drop(); // Value is no longer needed. 246 frame_->Drop(); // Value is no longer needed.
250 } 247 }
251 248
252 // Generate code to 'execute' declarations and initialize functions 249 // Generate code to 'execute' declarations and initialize functions
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); 514 frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
518 } 515 }
519 } 516 }
520 517
521 518
522 void CodeGenerator::UnloadReference(Reference* ref) { 519 void CodeGenerator::UnloadReference(Reference* ref) {
523 // Pop a reference from the stack while preserving TOS. 520 // Pop a reference from the stack while preserving TOS.
524 Comment cmnt(masm_, "[ UnloadReference"); 521 Comment cmnt(masm_, "[ UnloadReference");
525 int size = ref->size(); 522 int size = ref->size();
526 if (size == 1) { 523 if (size == 1) {
527 frame_->Pop(eax); 524 frame_->EmitPop(eax);
528 __ mov(frame_->Top(), eax); 525 __ mov(frame_->Top(), eax);
529 } else if (size > 1) { 526 } else if (size > 1) {
530 frame_->Pop(eax); 527 frame_->EmitPop(eax);
531 frame_->Drop(size); 528 frame_->Drop(size);
532 frame_->EmitPush(eax); 529 frame_->EmitPush(eax);
533 } 530 }
534 } 531 }
535 532
536 533
537 class ToBooleanStub: public CodeStub { 534 class ToBooleanStub: public CodeStub {
538 public: 535 public:
539 ToBooleanStub() { } 536 ToBooleanStub() { }
540 537
541 void Generate(MacroAssembler* masm); 538 void Generate(MacroAssembler* masm);
542 539
543 private: 540 private:
544 Major MajorKey() { return ToBoolean; } 541 Major MajorKey() { return ToBoolean; }
545 int MinorKey() { return 0; } 542 int MinorKey() { return 0; }
546 }; 543 };
547 544
548 545
549 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and 546 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
550 // convert it to a boolean in the condition code register or jump to 547 // convert it to a boolean in the condition code register or jump to
551 // 'false_target'/'true_target' as appropriate. 548 // 'false_target'/'true_target' as appropriate.
552 void CodeGenerator::ToBoolean(JumpTarget* true_target, JumpTarget* false_target) { 549 void CodeGenerator::ToBoolean(JumpTarget* true_target, JumpTarget* false_target) {
553 Comment cmnt(masm_, "[ ToBoolean"); 550 Comment cmnt(masm_, "[ ToBoolean");
554 551
555 // The value to convert should be popped from the stack. 552 // The value to convert should be popped from the stack.
556 frame_->Pop(eax); 553 frame_->EmitPop(eax);
557 554
558 // Fast case checks. 555 // Fast case checks.
559 556
560 // 'false' => false. 557 // 'false' => false.
561 __ cmp(eax, Factory::false_value()); 558 __ cmp(eax, Factory::false_value());
562 false_target->Branch(equal); 559 false_target->Branch(equal);
563 560
564 // 'true' => true. 561 // 'true' => true.
565 __ cmp(eax, Factory::true_value()); 562 __ cmp(eax, Factory::true_value());
566 true_target->Branch(equal); 563 true_target->Branch(equal);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 701
705 702
706 void CodeGenerator::GenericBinaryOperation(Token::Value op, 703 void CodeGenerator::GenericBinaryOperation(Token::Value op,
707 StaticType* type, 704 StaticType* type,
708 OverwriteMode overwrite_mode) { 705 OverwriteMode overwrite_mode) {
709 Comment cmnt(masm_, "[ BinaryOperation"); 706 Comment cmnt(masm_, "[ BinaryOperation");
710 Comment cmnt_token(masm_, Token::String(op)); 707 Comment cmnt_token(masm_, Token::String(op));
711 708
712 if (op == Token::COMMA) { 709 if (op == Token::COMMA) {
713 // Simply discard left value. 710 // Simply discard left value.
714 frame_->Pop(eax); 711 frame_->EmitPop(eax);
715 frame_->Drop(); 712 frame_->Drop();
716 frame_->EmitPush(eax); 713 frame_->EmitPush(eax);
717 return; 714 return;
718 } 715 }
719 716
720 // Set the flags based on the operation, type and loop nesting level. 717 // Set the flags based on the operation, type and loop nesting level.
721 GenericBinaryFlags flags; 718 GenericBinaryFlags flags;
722 switch (op) { 719 switch (op) {
723 case Token::BIT_OR: 720 case Token::BIT_OR:
724 case Token::BIT_AND: 721 case Token::BIT_AND:
(...skipping 15 matching lines...) Expand all
740 ? SMI_CODE_INLINED 737 ? SMI_CODE_INLINED
741 : SMI_CODE_IN_STUB; 738 : SMI_CODE_IN_STUB;
742 break; 739 break;
743 } 740 }
744 741
745 if (flags == SMI_CODE_INLINED) { 742 if (flags == SMI_CODE_INLINED) {
746 // Create a new deferred code for the slow-case part. 743 // Create a new deferred code for the slow-case part.
747 DeferredInlineBinaryOperation* deferred = 744 DeferredInlineBinaryOperation* deferred =
748 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags); 745 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags);
749 // Fetch the operands from the stack. 746 // Fetch the operands from the stack.
750 frame_->Pop(ebx); // get y 747 frame_->EmitPop(ebx); // get y
751 __ mov(eax, frame_->Top()); // get x 748 __ mov(eax, frame_->Top()); // get x
752 // Generate the inline part of the code. 749 // Generate the inline part of the code.
753 deferred->GenerateInlineCode(); 750 deferred->GenerateInlineCode();
754 // Put result back on the stack. It seems somewhat weird to let 751 // Put result back on the stack. It seems somewhat weird to let
755 // the deferred code jump back before the assignment to the frame 752 // 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 753 // top, but this is just to let the peephole optimizer get rid of
757 // more code. 754 // more code.
758 __ bind(deferred->exit()); 755 __ bind(deferred->exit());
759 __ mov(frame_->Top(), eax); 756 __ mov(frame_->Top(), eax);
760 } else { 757 } else {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 928
932 switch (op) { 929 switch (op) {
933 case Token::ADD: { 930 case Token::ADD: {
934 DeferredCode* deferred = NULL; 931 DeferredCode* deferred = NULL;
935 if (!reversed) { 932 if (!reversed) {
936 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); 933 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode);
937 } else { 934 } else {
938 deferred = new DeferredInlinedSmiAddReversed(this, int_value, 935 deferred = new DeferredInlinedSmiAddReversed(this, int_value,
939 overwrite_mode); 936 overwrite_mode);
940 } 937 }
941 frame_->Pop(eax); 938 frame_->EmitPop(eax);
942 __ add(Operand(eax), Immediate(value)); 939 __ add(Operand(eax), Immediate(value));
943 __ j(overflow, deferred->enter(), not_taken); 940 __ j(overflow, deferred->enter(), not_taken);
944 __ test(eax, Immediate(kSmiTagMask)); 941 __ test(eax, Immediate(kSmiTagMask));
945 __ j(not_zero, deferred->enter(), not_taken); 942 __ j(not_zero, deferred->enter(), not_taken);
946 __ bind(deferred->exit()); 943 __ bind(deferred->exit());
947 frame_->EmitPush(eax); 944 frame_->EmitPush(eax);
948 break; 945 break;
949 } 946 }
950 947
951 case Token::SUB: { 948 case Token::SUB: {
952 DeferredCode* deferred = NULL; 949 DeferredCode* deferred = NULL;
953 frame_->Pop(eax); 950 frame_->EmitPop(eax);
954 if (!reversed) { 951 if (!reversed) {
955 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); 952 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode);
956 __ sub(Operand(eax), Immediate(value)); 953 __ sub(Operand(eax), Immediate(value));
957 } else { 954 } else {
958 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); 955 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode);
959 __ mov(edx, Operand(eax)); 956 __ mov(edx, Operand(eax));
960 __ mov(eax, Immediate(value)); 957 __ mov(eax, Immediate(value));
961 __ sub(eax, Operand(edx)); 958 __ sub(eax, Operand(edx));
962 } 959 }
963 __ j(overflow, deferred->enter(), not_taken); 960 __ j(overflow, deferred->enter(), not_taken);
964 __ test(eax, Immediate(kSmiTagMask)); 961 __ test(eax, Immediate(kSmiTagMask));
965 __ j(not_zero, deferred->enter(), not_taken); 962 __ j(not_zero, deferred->enter(), not_taken);
966 __ bind(deferred->exit()); 963 __ bind(deferred->exit());
967 frame_->EmitPush(eax); 964 frame_->EmitPush(eax);
968 break; 965 break;
969 } 966 }
970 967
971 case Token::SAR: { 968 case Token::SAR: {
972 if (reversed) { 969 if (reversed) {
973 frame_->Pop(eax); 970 frame_->EmitPop(eax);
974 frame_->EmitPush(Immediate(value)); 971 frame_->EmitPush(Immediate(value));
975 frame_->EmitPush(eax); 972 frame_->EmitPush(eax);
976 GenericBinaryOperation(op, type, overwrite_mode); 973 GenericBinaryOperation(op, type, overwrite_mode);
977 } else { 974 } else {
978 int shift_value = int_value & 0x1f; // only least significant 5 bits 975 int shift_value = int_value & 0x1f; // only least significant 5 bits
979 DeferredCode* deferred = 976 DeferredCode* deferred =
980 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, 977 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value,
981 overwrite_mode); 978 overwrite_mode);
982 frame_->Pop(eax); 979 frame_->EmitPop(eax);
983 __ test(eax, Immediate(kSmiTagMask)); 980 __ test(eax, Immediate(kSmiTagMask));
984 __ j(not_zero, deferred->enter(), not_taken); 981 __ j(not_zero, deferred->enter(), not_taken);
985 __ sar(eax, shift_value); 982 __ sar(eax, shift_value);
986 __ and_(eax, ~kSmiTagMask); 983 __ and_(eax, ~kSmiTagMask);
987 __ bind(deferred->exit()); 984 __ bind(deferred->exit());
988 frame_->EmitPush(eax); 985 frame_->EmitPush(eax);
989 } 986 }
990 break; 987 break;
991 } 988 }
992 989
993 case Token::SHR: { 990 case Token::SHR: {
994 if (reversed) { 991 if (reversed) {
995 frame_->Pop(eax); 992 frame_->EmitPop(eax);
996 frame_->EmitPush(Immediate(value)); 993 frame_->EmitPush(Immediate(value));
997 frame_->EmitPush(eax); 994 frame_->EmitPush(eax);
998 GenericBinaryOperation(op, type, overwrite_mode); 995 GenericBinaryOperation(op, type, overwrite_mode);
999 } else { 996 } else {
1000 int shift_value = int_value & 0x1f; // only least significant 5 bits 997 int shift_value = int_value & 0x1f; // only least significant 5 bits
1001 DeferredCode* deferred = 998 DeferredCode* deferred =
1002 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, 999 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value,
1003 overwrite_mode); 1000 overwrite_mode);
1004 frame_->Pop(eax); 1001 frame_->EmitPop(eax);
1005 __ test(eax, Immediate(kSmiTagMask)); 1002 __ test(eax, Immediate(kSmiTagMask));
1006 __ mov(ebx, Operand(eax)); 1003 __ mov(ebx, Operand(eax));
1007 __ j(not_zero, deferred->enter(), not_taken); 1004 __ j(not_zero, deferred->enter(), not_taken);
1008 __ sar(ebx, kSmiTagSize); 1005 __ sar(ebx, kSmiTagSize);
1009 __ shr(ebx, shift_value); 1006 __ shr(ebx, shift_value);
1010 __ test(ebx, Immediate(0xc0000000)); 1007 __ test(ebx, Immediate(0xc0000000));
1011 __ j(not_zero, deferred->enter(), not_taken); 1008 __ j(not_zero, deferred->enter(), not_taken);
1012 // tag result and store it in TOS (eax) 1009 // tag result and store it in TOS (eax)
1013 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1010 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1014 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); 1011 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
1015 __ bind(deferred->exit()); 1012 __ bind(deferred->exit());
1016 frame_->EmitPush(eax); 1013 frame_->EmitPush(eax);
1017 } 1014 }
1018 break; 1015 break;
1019 } 1016 }
1020 1017
1021 case Token::SHL: { 1018 case Token::SHL: {
1022 if (reversed) { 1019 if (reversed) {
1023 frame_->Pop(eax); 1020 frame_->EmitPop(eax);
1024 frame_->EmitPush(Immediate(value)); 1021 frame_->EmitPush(Immediate(value));
1025 frame_->EmitPush(eax); 1022 frame_->EmitPush(eax);
1026 GenericBinaryOperation(op, type, overwrite_mode); 1023 GenericBinaryOperation(op, type, overwrite_mode);
1027 } else { 1024 } else {
1028 int shift_value = int_value & 0x1f; // only least significant 5 bits 1025 int shift_value = int_value & 0x1f; // only least significant 5 bits
1029 DeferredCode* deferred = 1026 DeferredCode* deferred =
1030 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, 1027 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value,
1031 overwrite_mode); 1028 overwrite_mode);
1032 frame_->Pop(eax); 1029 frame_->EmitPop(eax);
1033 __ test(eax, Immediate(kSmiTagMask)); 1030 __ test(eax, Immediate(kSmiTagMask));
1034 __ mov(ebx, Operand(eax)); 1031 __ mov(ebx, Operand(eax));
1035 __ j(not_zero, deferred->enter(), not_taken); 1032 __ j(not_zero, deferred->enter(), not_taken);
1036 __ sar(ebx, kSmiTagSize); 1033 __ sar(ebx, kSmiTagSize);
1037 __ shl(ebx, shift_value); 1034 __ shl(ebx, shift_value);
1038 __ lea(ecx, Operand(ebx, 0x40000000)); 1035 __ lea(ecx, Operand(ebx, 0x40000000));
1039 __ test(ecx, Immediate(0x80000000)); 1036 __ test(ecx, Immediate(0x80000000));
1040 __ j(not_zero, deferred->enter(), not_taken); 1037 __ j(not_zero, deferred->enter(), not_taken);
1041 // tag result and store it in TOS (eax) 1038 // tag result and store it in TOS (eax)
1042 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1039 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1043 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); 1040 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
1044 __ bind(deferred->exit()); 1041 __ bind(deferred->exit());
1045 frame_->EmitPush(eax); 1042 frame_->EmitPush(eax);
1046 } 1043 }
1047 break; 1044 break;
1048 } 1045 }
1049 1046
1050 case Token::BIT_OR: 1047 case Token::BIT_OR:
1051 case Token::BIT_XOR: 1048 case Token::BIT_XOR:
1052 case Token::BIT_AND: { 1049 case Token::BIT_AND: {
1053 DeferredCode* deferred = NULL; 1050 DeferredCode* deferred = NULL;
1054 if (!reversed) { 1051 if (!reversed) {
1055 deferred = new DeferredInlinedSmiOperation(this, op, int_value, 1052 deferred = new DeferredInlinedSmiOperation(this, op, int_value,
1056 overwrite_mode); 1053 overwrite_mode);
1057 } else { 1054 } else {
1058 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, 1055 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value,
1059 overwrite_mode); 1056 overwrite_mode);
1060 } 1057 }
1061 frame_->Pop(eax); 1058 frame_->EmitPop(eax);
1062 __ test(eax, Immediate(kSmiTagMask)); 1059 __ test(eax, Immediate(kSmiTagMask));
1063 __ j(not_zero, deferred->enter(), not_taken); 1060 __ j(not_zero, deferred->enter(), not_taken);
1064 if (op == Token::BIT_AND) { 1061 if (op == Token::BIT_AND) {
1065 __ and_(Operand(eax), Immediate(value)); 1062 __ and_(Operand(eax), Immediate(value));
1066 } else if (op == Token::BIT_XOR) { 1063 } else if (op == Token::BIT_XOR) {
1067 __ xor_(Operand(eax), Immediate(value)); 1064 __ xor_(Operand(eax), Immediate(value));
1068 } else { 1065 } else {
1069 ASSERT(op == Token::BIT_OR); 1066 ASSERT(op == Token::BIT_OR);
1070 __ or_(Operand(eax), Immediate(value)); 1067 __ or_(Operand(eax), Immediate(value));
1071 } 1068 }
1072 __ bind(deferred->exit()); 1069 __ bind(deferred->exit());
1073 frame_->EmitPush(eax); 1070 frame_->EmitPush(eax);
1074 break; 1071 break;
1075 } 1072 }
1076 1073
1077 default: { 1074 default: {
1078 if (!reversed) { 1075 if (!reversed) {
1079 frame_->EmitPush(Immediate(value)); 1076 frame_->EmitPush(Immediate(value));
1080 } else { 1077 } else {
1081 frame_->Pop(eax); 1078 frame_->EmitPop(eax);
1082 frame_->EmitPush(Immediate(value)); 1079 frame_->EmitPush(Immediate(value));
1083 frame_->EmitPush(eax); 1080 frame_->EmitPush(eax);
1084 } 1081 }
1085 GenericBinaryOperation(op, type, overwrite_mode); 1082 GenericBinaryOperation(op, type, overwrite_mode);
1086 break; 1083 break;
1087 } 1084 }
1088 } 1085 }
1089 } 1086 }
1090 1087
1091 1088
(...skipping 25 matching lines...) Expand all
1117 }; 1114 };
1118 1115
1119 1116
1120 void CodeGenerator::Comparison(Condition cc, bool strict) { 1117 void CodeGenerator::Comparison(Condition cc, bool strict) {
1121 // Strict only makes sense for equality comparisons. 1118 // Strict only makes sense for equality comparisons.
1122 ASSERT(!strict || cc == equal); 1119 ASSERT(!strict || cc == equal);
1123 1120
1124 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1121 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1125 if (cc == greater || cc == less_equal) { 1122 if (cc == greater || cc == less_equal) {
1126 cc = ReverseCondition(cc); 1123 cc = ReverseCondition(cc);
1127 frame_->Pop(edx); 1124 frame_->EmitPop(edx);
1128 frame_->Pop(eax); 1125 frame_->EmitPop(eax);
1129 } else { 1126 } else {
1130 frame_->Pop(eax); 1127 frame_->EmitPop(eax);
1131 frame_->Pop(edx); 1128 frame_->EmitPop(edx);
1132 } 1129 }
1133 1130
1134 // Check for the smi case. 1131 // Check for the smi case.
1135 JumpTarget is_smi(this); 1132 JumpTarget is_smi(this);
1136 JumpTarget done(this); 1133 JumpTarget done(this);
1137 __ mov(ecx, Operand(eax)); 1134 __ mov(ecx, Operand(eax));
1138 __ or_(ecx, Operand(edx)); 1135 __ or_(ecx, Operand(edx));
1139 __ test(ecx, Immediate(kSmiTagMask)); 1136 __ test(ecx, Immediate(kSmiTagMask));
1140 is_smi.Branch(zero, taken); 1137 is_smi.Branch(zero, taken);
1141 1138
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 Handle<Object> value, 1190 Handle<Object> value,
1194 bool strict) { 1191 bool strict) {
1195 // Strict only makes sense for equality comparisons. 1192 // Strict only makes sense for equality comparisons.
1196 ASSERT(!strict || cc == equal); 1193 ASSERT(!strict || cc == equal);
1197 1194
1198 int int_value = Smi::cast(*value)->value(); 1195 int int_value = Smi::cast(*value)->value();
1199 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); 1196 ASSERT(is_intn(int_value, kMaxSmiInlinedBits));
1200 1197
1201 SmiComparisonDeferred* deferred = 1198 SmiComparisonDeferred* deferred =
1202 new SmiComparisonDeferred(this, cc, strict, int_value); 1199 new SmiComparisonDeferred(this, cc, strict, int_value);
1203 frame_->Pop(eax); 1200 frame_->EmitPop(eax);
1204 __ test(eax, Immediate(kSmiTagMask)); 1201 __ test(eax, Immediate(kSmiTagMask));
1205 __ j(not_zero, deferred->enter(), not_taken); 1202 __ j(not_zero, deferred->enter(), not_taken);
1206 // Test smi equality by pointer comparison. 1203 // Test smi equality by pointer comparison.
1207 __ cmp(Operand(eax), Immediate(value)); 1204 __ cmp(Operand(eax), Immediate(value));
1208 __ bind(deferred->exit()); 1205 __ bind(deferred->exit());
1209 cc_reg_ = cc; 1206 cc_reg_ = cc;
1210 } 1207 }
1211 1208
1212 1209
1213 class CallFunctionStub: public CodeStub { 1210 class CallFunctionStub: public CodeStub {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 1271
1275 1272
1276 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { 1273 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
1277 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { 1274 for (int i = 0; frame_ != NULL && i < statements->length(); i++) {
1278 Visit(statements->at(i)); 1275 Visit(statements->at(i));
1279 } 1276 }
1280 } 1277 }
1281 1278
1282 1279
1283 void CodeGenerator::VisitBlock(Block* node) { 1280 void CodeGenerator::VisitBlock(Block* node) {
1281 frame_->SpillAll();
1284 Comment cmnt(masm_, "[ Block"); 1282 Comment cmnt(masm_, "[ Block");
1285 RecordStatementPosition(node); 1283 RecordStatementPosition(node);
1286 node->set_break_stack_height(break_stack_height_); 1284 node->set_break_stack_height(break_stack_height_);
1287 node->break_target()->set_code_generator(this); 1285 node->break_target()->set_code_generator(this);
1288 VisitStatements(node->statements()); 1286 VisitStatements(node->statements());
1289 if (node->break_target()->is_linked()) { 1287 if (node->break_target()->is_linked()) {
1290 node->break_target()->Bind(); 1288 node->break_target()->Bind();
1291 } 1289 }
1292 } 1290 }
1293 1291
1294 1292
1295 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1293 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1294 frame_->SpillAll();
1296 frame_->EmitPush(Immediate(pairs)); 1295 frame_->EmitPush(Immediate(pairs));
1297 frame_->EmitPush(esi); 1296 frame_->EmitPush(esi);
1298 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 1297 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
1299 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1298 frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1300 // Return value is ignored. 1299 // Return value is ignored.
1301 } 1300 }
1302 1301
1303 1302
1304 void CodeGenerator::VisitDeclaration(Declaration* node) { 1303 void CodeGenerator::VisitDeclaration(Declaration* node) {
1304 frame_->SpillAll();
1305
1305 Comment cmnt(masm_, "[ Declaration"); 1306 Comment cmnt(masm_, "[ Declaration");
1306 Variable* var = node->proxy()->var(); 1307 Variable* var = node->proxy()->var();
1307 ASSERT(var != NULL); // must have been resolved 1308 ASSERT(var != NULL); // must have been resolved
1308 Slot* slot = var->slot(); 1309 Slot* slot = var->slot();
1309 1310
1310 // If it was not possible to allocate the variable at compile time, 1311 // 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 1312 // we need to "declare" it at runtime to make sure it actually
1312 // exists in the local context. 1313 // exists in the local context.
1313 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1314 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1314 // Variables with a "LOOKUP" slot were introduced as non-locals 1315 // Variables with a "LOOKUP" slot were introduced as non-locals
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 // Get rid of the assigned value (declarations are statements). It's 1357 // Get rid of the assigned value (declarations are statements). It's
1357 // safe to pop the value lying on top of the reference before unloading 1358 // safe to pop the value lying on top of the reference before unloading
1358 // the reference itself (which preserves the top of stack) because we 1359 // the reference itself (which preserves the top of stack) because we
1359 // know that it is a zero-sized reference. 1360 // know that it is a zero-sized reference.
1360 frame_->Drop(); 1361 frame_->Drop();
1361 } 1362 }
1362 } 1363 }
1363 1364
1364 1365
1365 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { 1366 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) {
1367 frame_->SpillAll();
1366 Comment cmnt(masm_, "[ ExpressionStatement"); 1368 Comment cmnt(masm_, "[ ExpressionStatement");
1367 RecordStatementPosition(node); 1369 RecordStatementPosition(node);
1368 Expression* expression = node->expression(); 1370 Expression* expression = node->expression();
1369 expression->MarkAsStatement(); 1371 expression->MarkAsStatement();
1370 Load(expression); 1372 Load(expression);
1371 // Remove the lingering expression result from the top of stack. 1373 // Remove the lingering expression result from the top of stack.
1372 frame_->Drop(); 1374 frame_->Drop();
1373 } 1375 }
1374 1376
1375 1377
1376 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { 1378 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
1379 frame_->SpillAll();
1377 Comment cmnt(masm_, "// EmptyStatement"); 1380 Comment cmnt(masm_, "// EmptyStatement");
1378 // nothing to do 1381 // nothing to do
1379 } 1382 }
1380 1383
1381 1384
1382 void CodeGenerator::VisitIfStatement(IfStatement* node) { 1385 void CodeGenerator::VisitIfStatement(IfStatement* node) {
1386 frame_->SpillAll();
1383 Comment cmnt(masm_, "[ IfStatement"); 1387 Comment cmnt(masm_, "[ IfStatement");
1384 // Generate different code depending on which parts of the if statement 1388 // Generate different code depending on which parts of the if statement
1385 // are present or not. 1389 // are present or not.
1386 bool has_then_stm = node->HasThenStatement(); 1390 bool has_then_stm = node->HasThenStatement();
1387 bool has_else_stm = node->HasElseStatement(); 1391 bool has_else_stm = node->HasElseStatement();
1388 1392
1389 RecordStatementPosition(node); 1393 RecordStatementPosition(node);
1390 JumpTarget exit(this); 1394 JumpTarget exit(this);
1391 if (has_then_stm && has_else_stm) { 1395 if (has_then_stm && has_else_stm) {
1392 JumpTarget then(this); 1396 JumpTarget then(this);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1470 } 1474 }
1471 1475
1472 1476
1473 void CodeGenerator::CleanStack(int num_bytes) { 1477 void CodeGenerator::CleanStack(int num_bytes) {
1474 ASSERT(num_bytes % kPointerSize == 0); 1478 ASSERT(num_bytes % kPointerSize == 0);
1475 frame_->Drop(num_bytes / kPointerSize); 1479 frame_->Drop(num_bytes / kPointerSize);
1476 } 1480 }
1477 1481
1478 1482
1479 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { 1483 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) {
1484 frame_->SpillAll();
1480 Comment cmnt(masm_, "[ ContinueStatement"); 1485 Comment cmnt(masm_, "[ ContinueStatement");
1481 RecordStatementPosition(node); 1486 RecordStatementPosition(node);
1482 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1487 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1483 node->target()->continue_target()->Jump(); 1488 node->target()->continue_target()->Jump();
1484 } 1489 }
1485 1490
1486 1491
1487 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { 1492 void CodeGenerator::VisitBreakStatement(BreakStatement* node) {
1493 frame_->SpillAll();
1488 Comment cmnt(masm_, "[ BreakStatement"); 1494 Comment cmnt(masm_, "[ BreakStatement");
1489 RecordStatementPosition(node); 1495 RecordStatementPosition(node);
1490 CleanStack(break_stack_height_ - node->target()->break_stack_height()); 1496 CleanStack(break_stack_height_ - node->target()->break_stack_height());
1491 node->target()->break_target()->Jump(); 1497 node->target()->break_target()->Jump();
1492 } 1498 }
1493 1499
1494 1500
1495 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { 1501 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
1502 frame_->SpillAll();
1496 Comment cmnt(masm_, "[ ReturnStatement"); 1503 Comment cmnt(masm_, "[ ReturnStatement");
1497 RecordStatementPosition(node); 1504 RecordStatementPosition(node);
1498 Load(node->expression()); 1505 Load(node->expression());
1499 1506
1500 // Move the function result into eax 1507 // Move the function result into eax
1501 frame_->Pop(eax); 1508 frame_->EmitPop(eax);
1502 1509
1503 // If we're inside a try statement or the return instruction 1510 // If we're inside a try statement or the return instruction
1504 // sequence has been generated, we just jump to that 1511 // sequence has been generated, we just jump to that
1505 // point. Otherwise, we generate the return instruction sequence and 1512 // point. Otherwise, we generate the return instruction sequence and
1506 // bind the function return label. 1513 // bind the function return label.
1507 if (is_inside_try_ || function_return_.is_bound()) { 1514 if (is_inside_try_ || function_return_.is_bound()) {
1508 function_return_.Jump(); 1515 function_return_.Jump();
1509 } else { 1516 } else {
1510 function_return_.Bind(); 1517 function_return_.Bind();
1511 if (FLAG_trace) { 1518 if (FLAG_trace) {
(...skipping 13 matching lines...) Expand all
1525 1532
1526 // Check that the size of the code used for returning matches what is 1533 // Check that the size of the code used for returning matches what is
1527 // expected by the debugger. 1534 // expected by the debugger.
1528 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, 1535 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
1529 __ SizeOfCodeGeneratedSince(&check_exit_codesize)); 1536 __ SizeOfCodeGeneratedSince(&check_exit_codesize));
1530 } 1537 }
1531 } 1538 }
1532 1539
1533 1540
1534 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1541 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1542 frame_->SpillAll();
1535 Comment cmnt(masm_, "[ WithEnterStatement"); 1543 Comment cmnt(masm_, "[ WithEnterStatement");
1536 RecordStatementPosition(node); 1544 RecordStatementPosition(node);
1537 Load(node->expression()); 1545 Load(node->expression());
1538 frame_->CallRuntime(Runtime::kPushContext, 1); 1546 frame_->CallRuntime(Runtime::kPushContext, 1);
1539 1547
1540 if (kDebug) { 1548 if (kDebug) {
1541 JumpTarget verified_true(this); 1549 JumpTarget verified_true(this);
1542 // Verify eax and esi are the same in debug mode 1550 // Verify eax and esi are the same in debug mode
1543 __ cmp(eax, Operand(esi)); 1551 __ cmp(eax, Operand(esi));
1544 verified_true.Branch(equal); 1552 verified_true.Branch(equal);
1545 __ int3(); 1553 __ int3();
1546 verified_true.Bind(); 1554 verified_true.Bind();
1547 } 1555 }
1548 1556
1549 // Update context local. 1557 // Update context local.
1550 __ mov(frame_->Context(), esi); 1558 __ mov(frame_->Context(), esi);
1551 } 1559 }
1552 1560
1553 1561
1554 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { 1562 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
1563 frame_->SpillAll();
1555 Comment cmnt(masm_, "[ WithExitStatement"); 1564 Comment cmnt(masm_, "[ WithExitStatement");
1556 // Pop context. 1565 // Pop context.
1557 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX)); 1566 __ mov(esi, ContextOperand(esi, Context::PREVIOUS_INDEX));
1558 // Update context local. 1567 // Update context local.
1559 __ mov(frame_->Context(), esi); 1568 __ mov(frame_->Context(), esi);
1560 } 1569 }
1561 1570
1562 1571
1563 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { 1572 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
1564 return kFastSwitchMaxOverheadFactor; 1573 return kFastSwitchMaxOverheadFactor;
(...skipping 14 matching lines...) Expand all
1579 Vector<JumpTarget*> case_targets, 1588 Vector<JumpTarget*> case_targets,
1580 Vector<JumpTarget> case_labels) { 1589 Vector<JumpTarget> case_labels) {
1581 // Notice: Internal references, used by both the jmp instruction and 1590 // Notice: Internal references, used by both the jmp instruction and
1582 // the table entries, need to be relocated if the buffer grows. This 1591 // the table entries, need to be relocated if the buffer grows. This
1583 // prevents the forward use of Labels, since a displacement cannot 1592 // prevents the forward use of Labels, since a displacement cannot
1584 // survive relocation, and it also cannot safely be distinguished 1593 // survive relocation, and it also cannot safely be distinguished
1585 // from a real address. Instead we put in zero-values as 1594 // from a real address. Instead we put in zero-values as
1586 // placeholders, and fill in the addresses after the labels have been 1595 // placeholders, and fill in the addresses after the labels have been
1587 // bound. 1596 // bound.
1588 1597
1589 frame_->Pop(eax); // supposed Smi 1598 frame_->EmitPop(eax); // supposed Smi
1590 // check range of value, if outside [0..length-1] jump to default/end label. 1599 // check range of value, if outside [0..length-1] jump to default/end label.
1591 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 1600 ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1592 1601
1593 // Test whether input is a HeapNumber that is really a Smi 1602 // Test whether input is a HeapNumber that is really a Smi
1594 JumpTarget is_smi(this); 1603 JumpTarget is_smi(this);
1595 __ test(eax, Immediate(kSmiTagMask)); 1604 __ test(eax, Immediate(kSmiTagMask));
1596 is_smi.Branch(equal); 1605 is_smi.Branch(equal);
1597 // It's a heap object, not a Smi or a Failure 1606 // It's a heap object, not a Smi or a Failure
1598 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1607 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1599 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1608 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1631 1640
1632 for (int i = 0, entry_pos = table_start.label()->pos(); 1641 for (int i = 0, entry_pos = table_start.label()->pos();
1633 i < range; 1642 i < range;
1634 i++, entry_pos += sizeof(uint32_t)) { 1643 i++, entry_pos += sizeof(uint32_t)) {
1635 __ WriteInternalReference(entry_pos, *case_targets[i]->label()); 1644 __ WriteInternalReference(entry_pos, *case_targets[i]->label());
1636 } 1645 }
1637 } 1646 }
1638 1647
1639 1648
1640 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { 1649 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
1650 frame_->SpillAll();
1641 Comment cmnt(masm_, "[ SwitchStatement"); 1651 Comment cmnt(masm_, "[ SwitchStatement");
1642 RecordStatementPosition(node); 1652 RecordStatementPosition(node);
1643 node->set_break_stack_height(break_stack_height_); 1653 node->set_break_stack_height(break_stack_height_);
1644 node->break_target()->set_code_generator(this); 1654 node->break_target()->set_code_generator(this);
1645 1655
1646 Load(node->tag()); 1656 Load(node->tag());
1647 1657
1648 if (TryGenerateFastCaseSwitchStatement(node)) { 1658 if (TryGenerateFastCaseSwitchStatement(node)) {
1649 return; 1659 return;
1650 } 1660 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1720 fall_through.Bind(); 1730 fall_through.Bind();
1721 } 1731 }
1722 1732
1723 if (node->break_target()->is_linked()) { 1733 if (node->break_target()->is_linked()) {
1724 node->break_target()->Bind(); 1734 node->break_target()->Bind();
1725 } 1735 }
1726 } 1736 }
1727 1737
1728 1738
1729 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1739 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1740 frame_->SpillAll();
1730 Comment cmnt(masm_, "[ LoopStatement"); 1741 Comment cmnt(masm_, "[ LoopStatement");
1731 RecordStatementPosition(node); 1742 RecordStatementPosition(node);
1732 node->set_break_stack_height(break_stack_height_); 1743 node->set_break_stack_height(break_stack_height_);
1733 node->break_target()->set_code_generator(this); 1744 node->break_target()->set_code_generator(this);
1734 node->continue_target()->set_code_generator(this); 1745 node->continue_target()->set_code_generator(this);
1735 1746
1736 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a 1747 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
1737 // known result for the test expression, with no side effects. 1748 // known result for the test expression, with no side effects.
1738 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 1749 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
1739 if (node->cond() == NULL) { 1750 if (node->cond() == NULL) {
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1898 } 1909 }
1899 1910
1900 DecrementLoopNesting(); 1911 DecrementLoopNesting();
1901 if (node->break_target()->is_linked()) { 1912 if (node->break_target()->is_linked()) {
1902 node->break_target()->Bind(); 1913 node->break_target()->Bind();
1903 } 1914 }
1904 } 1915 }
1905 1916
1906 1917
1907 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 1918 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1919 frame_->SpillAll();
1908 Comment cmnt(masm_, "[ ForInStatement"); 1920 Comment cmnt(masm_, "[ ForInStatement");
1909 RecordStatementPosition(node); 1921 RecordStatementPosition(node);
1910 1922
1911 // We keep stuff on the stack while the body is executing. 1923 // We keep stuff on the stack while the body is executing.
1912 // Record it, so that a break/continue crossing this statement 1924 // Record it, so that a break/continue crossing this statement
1913 // can restore the stack. 1925 // can restore the stack.
1914 const int kForInStackSize = 5 * kPointerSize; 1926 const int kForInStackSize = 5 * kPointerSize;
1915 break_stack_height_ += kForInStackSize; 1927 break_stack_height_ += kForInStackSize;
1916 node->set_break_stack_height(break_stack_height_); 1928 node->set_break_stack_height(break_stack_height_);
1917 node->break_target()->set_code_generator(this); 1929 node->break_target()->set_code_generator(this);
1918 node->continue_target()->set_code_generator(this); 1930 node->continue_target()->set_code_generator(this);
1919 1931
1920 JumpTarget primitive(this); 1932 JumpTarget primitive(this);
1921 JumpTarget jsobject(this); 1933 JumpTarget jsobject(this);
1922 JumpTarget fixed_array(this); 1934 JumpTarget fixed_array(this);
1923 JumpTarget entry(this); 1935 JumpTarget entry(this);
1924 JumpTarget end_del_check(this); 1936 JumpTarget end_del_check(this);
1925 JumpTarget cleanup(this); 1937 JumpTarget cleanup(this);
1926 JumpTarget exit(this); 1938 JumpTarget exit(this);
1927 1939
1928 // Get the object to enumerate over (converted to JSObject). 1940 // Get the object to enumerate over (converted to JSObject).
1929 Load(node->enumerable()); 1941 Load(node->enumerable());
1930 1942
1931 // Both SpiderMonkey and kjs ignore null and undefined in contrast 1943 // Both SpiderMonkey and kjs ignore null and undefined in contrast
1932 // to the specification. 12.6.4 mandates a call to ToObject. 1944 // to the specification. 12.6.4 mandates a call to ToObject.
1933 frame_->Pop(eax); 1945 frame_->EmitPop(eax);
1934 1946
1935 // eax: value to be iterated over 1947 // eax: value to be iterated over
1936 __ cmp(eax, Factory::undefined_value()); 1948 __ cmp(eax, Factory::undefined_value());
1937 exit.Branch(equal); 1949 exit.Branch(equal);
1938 __ cmp(eax, Factory::null_value()); 1950 __ cmp(eax, Factory::null_value());
1939 exit.Branch(equal); 1951 exit.Branch(equal);
1940 1952
1941 // Stack layout in body: 1953 // Stack layout in body:
1942 // [iteration counter (smi)] <- slot 0 1954 // [iteration counter (smi)] <- slot 0
1943 // [length of array] <- slot 1 1955 // [length of array] <- slot 1
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2065 // Discard the i'th entry pushed above or else the remainder of the 2077 // Discard the i'th entry pushed above or else the remainder of the
2066 // reference, whichever is currently on top of the stack. 2078 // reference, whichever is currently on top of the stack.
2067 frame_->Drop(); 2079 frame_->Drop();
2068 2080
2069 // Body. 2081 // Body.
2070 CheckStack(); // TODO(1222600): ignore if body contains calls. 2082 CheckStack(); // TODO(1222600): ignore if body contains calls.
2071 Visit(node->body()); 2083 Visit(node->body());
2072 2084
2073 // Next. 2085 // Next.
2074 node->continue_target()->Bind(); 2086 node->continue_target()->Bind();
2075 frame_->Pop(eax); 2087 frame_->EmitPop(eax);
2076 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 2088 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
2077 frame_->EmitPush(eax); 2089 frame_->EmitPush(eax);
2078 entry.Jump(); 2090 entry.Jump();
2079 2091
2080 // Cleanup. 2092 // Cleanup.
2081 cleanup.Bind(); 2093 cleanup.Bind();
2082 node->break_target()->Bind(); 2094 node->break_target()->Bind();
2083 frame_->Drop(5); 2095 frame_->Drop(5);
2084 2096
2085 // Exit. 2097 // Exit.
2086 exit.Bind(); 2098 exit.Bind();
2087 2099
2088 break_stack_height_ -= kForInStackSize; 2100 break_stack_height_ -= kForInStackSize;
2089 } 2101 }
2090 2102
2091 2103
2092 void CodeGenerator::VisitTryCatch(TryCatch* node) { 2104 void CodeGenerator::VisitTryCatch(TryCatch* node) {
2105 frame_->SpillAll();
2093 Comment cmnt(masm_, "[ TryCatch"); 2106 Comment cmnt(masm_, "[ TryCatch");
2094 2107
2095 JumpTarget try_block(this); 2108 JumpTarget try_block(this);
2096 JumpTarget exit(this); 2109 JumpTarget exit(this);
2097 2110
2098 try_block.Call(); 2111 try_block.Call();
2099 // --- Catch block --- 2112 // --- Catch block ---
2100 frame_->EmitPush(eax); 2113 frame_->EmitPush(eax);
2101 2114
2102 // Store the caught exception in the catch variable. 2115 // Store the caught exception in the catch variable.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2162 // handler structure. 2175 // handler structure.
2163 if (FLAG_debug_code) { 2176 if (FLAG_debug_code) {
2164 __ mov(eax, Operand::StaticVariable(handler_address)); 2177 __ mov(eax, Operand::StaticVariable(handler_address));
2165 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement)); 2178 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement));
2166 __ cmp(esp, Operand(eax)); 2179 __ cmp(esp, Operand(eax));
2167 __ Assert(equal, "stack pointer should point to top handler"); 2180 __ Assert(equal, "stack pointer should point to top handler");
2168 } 2181 }
2169 2182
2170 // If we can fall off the end of the try block, unlink from try chain. 2183 // If we can fall off the end of the try block, unlink from try chain.
2171 if (frame_ != NULL) { 2184 if (frame_ != NULL) {
2172 frame_->Pop(eax); 2185 frame_->EmitPop(eax);
2173 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp 2186 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp
2174 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2187 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2175 // next_sp popped. 2188 // next_sp popped.
2176 if (nof_unlinks > 0) { 2189 if (nof_unlinks > 0) {
2177 exit.Jump(); 2190 exit.Jump();
2178 } 2191 }
2179 } 2192 }
2180 2193
2181 // Generate unlink code for the (formerly) shadowing targets that have been 2194 // Generate unlink code for the (formerly) shadowing targets that have been
2182 // jumped to. 2195 // jumped to.
2183 for (int i = 0; i <= nof_escapes; i++) { 2196 for (int i = 0; i <= nof_escapes; i++) {
2184 if (shadows[i]->is_linked()) { 2197 if (shadows[i]->is_linked()) {
2185 // Unlink from try chain; be careful not to destroy the TOS. 2198 // Unlink from try chain; be careful not to destroy the TOS.
2186 shadows[i]->Bind(); 2199 shadows[i]->Bind();
2187 2200
2188 // Reload sp from the top handler, because some statements that we 2201 // Reload sp from the top handler, because some statements that we
2189 // break from (eg, for...in) may have left stuff on the stack. 2202 // break from (eg, for...in) may have left stuff on the stack.
2190 __ mov(edx, Operand::StaticVariable(handler_address)); 2203 __ mov(edx, Operand::StaticVariable(handler_address));
2191 const int kNextOffset = StackHandlerConstants::kNextOffset + 2204 const int kNextOffset = StackHandlerConstants::kNextOffset +
2192 StackHandlerConstants::kAddressDisplacement; 2205 StackHandlerConstants::kAddressDisplacement;
2193 __ lea(esp, Operand(edx, kNextOffset)); 2206 __ lea(esp, Operand(edx, kNextOffset));
2194 frame_->Forget(frame_->height() - handler_height); 2207 frame_->Forget(frame_->height() - handler_height);
2195 2208
2196 frame_->Pop(Operand::StaticVariable(handler_address)); 2209 frame_->EmitPop(Operand::StaticVariable(handler_address));
2197 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2210 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2198 // next_sp popped. 2211 // next_sp popped.
2199 shadows[i]->original_target()->Jump(); 2212 shadows[i]->original_target()->Jump();
2200 } 2213 }
2201 } 2214 }
2202 2215
2203 exit.Bind(); 2216 exit.Bind();
2204 } 2217 }
2205 2218
2206 2219
2207 void CodeGenerator::VisitTryFinally(TryFinally* node) { 2220 void CodeGenerator::VisitTryFinally(TryFinally* node) {
2221 frame_->SpillAll();
2208 Comment cmnt(masm_, "[ TryFinally"); 2222 Comment cmnt(masm_, "[ TryFinally");
2209 2223
2210 // State: Used to keep track of reason for entering the finally 2224 // State: Used to keep track of reason for entering the finally
2211 // block. Should probably be extended to hold information for 2225 // block. Should probably be extended to hold information for
2212 // break/continue from within the try block. 2226 // break/continue from within the try block.
2213 enum { FALLING, THROWING, JUMPING }; 2227 enum { FALLING, THROWING, JUMPING };
2214 2228
2215 JumpTarget unlink(this); 2229 JumpTarget unlink(this);
2216 JumpTarget try_block(this); 2230 JumpTarget try_block(this);
2217 JumpTarget finally_block(this); 2231 JumpTarget finally_block(this);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2288 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); 2302 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i)));
2289 unlink.Jump(); 2303 unlink.Jump();
2290 } 2304 }
2291 } 2305 }
2292 2306
2293 // Unlink from try chain; be careful not to destroy the TOS. 2307 // Unlink from try chain; be careful not to destroy the TOS.
2294 unlink.Bind(); 2308 unlink.Bind();
2295 // Reload sp from the top handler, because some statements that we 2309 // Reload sp from the top handler, because some statements that we
2296 // break from (eg, for...in) may have left stuff on the stack. 2310 // break from (eg, for...in) may have left stuff on the stack.
2297 // Preserve the TOS in a register across stack manipulation. 2311 // Preserve the TOS in a register across stack manipulation.
2298 frame_->Pop(eax); 2312 frame_->EmitPop(eax);
2299 ExternalReference handler_address(Top::k_handler_address); 2313 ExternalReference handler_address(Top::k_handler_address);
2300 __ mov(edx, Operand::StaticVariable(handler_address)); 2314 __ mov(edx, Operand::StaticVariable(handler_address));
2301 const int kNextOffset = StackHandlerConstants::kNextOffset + 2315 const int kNextOffset = StackHandlerConstants::kNextOffset +
2302 StackHandlerConstants::kAddressDisplacement; 2316 StackHandlerConstants::kAddressDisplacement;
2303 __ lea(esp, Operand(edx, kNextOffset)); 2317 __ lea(esp, Operand(edx, kNextOffset));
2304 frame_->Forget(frame_->height() - handler_height); 2318 frame_->Forget(frame_->height() - handler_height);
2305 2319
2306 frame_->Pop(Operand::StaticVariable(handler_address)); 2320 frame_->EmitPop(Operand::StaticVariable(handler_address));
2307 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2321 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2308 // Next_sp popped. 2322 // Next_sp popped.
2309 frame_->EmitPush(eax); 2323 frame_->EmitPush(eax);
2310 2324
2311 // --- Finally block --- 2325 // --- Finally block ---
2312 finally_block.Bind(); 2326 finally_block.Bind();
2313 2327
2314 // Push the state on the stack. 2328 // Push the state on the stack.
2315 frame_->EmitPush(ecx); 2329 frame_->EmitPush(ecx);
2316 2330
2317 // We keep two elements on the stack - the (possibly faked) result 2331 // We keep two elements on the stack - the (possibly faked) result
2318 // and the state - while evaluating the finally block. Record it, so 2332 // and the state - while evaluating the finally block. Record it, so
2319 // that a break/continue crossing this statement can restore the 2333 // that a break/continue crossing this statement can restore the
2320 // stack. 2334 // stack.
2321 const int kFinallyStackSize = 2 * kPointerSize; 2335 const int kFinallyStackSize = 2 * kPointerSize;
2322 break_stack_height_ += kFinallyStackSize; 2336 break_stack_height_ += kFinallyStackSize;
2323 2337
2324 // Generate code for the statements in the finally block. 2338 // Generate code for the statements in the finally block.
2325 VisitStatements(node->finally_block()->statements()); 2339 VisitStatements(node->finally_block()->statements());
2326 2340
2327 break_stack_height_ -= kFinallyStackSize; 2341 break_stack_height_ -= kFinallyStackSize;
2328 if (frame_ != NULL) { 2342 if (frame_ != NULL) {
2329 JumpTarget exit(this); 2343 JumpTarget exit(this);
2330 // Restore state and return value or faked TOS. 2344 // Restore state and return value or faked TOS.
2331 frame_->Pop(ecx); 2345 frame_->EmitPop(ecx);
2332 frame_->Pop(eax); 2346 frame_->EmitPop(eax);
2333 2347
2334 // Generate code to jump to the right destination for all used 2348 // Generate code to jump to the right destination for all used
2335 // (formerly) shadowing targets. 2349 // (formerly) shadowing targets.
2336 for (int i = 0; i <= nof_escapes; i++) { 2350 for (int i = 0; i <= nof_escapes; i++) {
2337 if (shadows[i]->is_bound()) { 2351 if (shadows[i]->is_bound()) {
2338 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); 2352 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i)));
2339 shadows[i]->original_target()->Branch(equal); 2353 shadows[i]->original_target()->Branch(equal);
2340 } 2354 }
2341 } 2355 }
2342 2356
2343 // Check if we need to rethrow the exception. 2357 // Check if we need to rethrow the exception.
2344 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); 2358 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
2345 exit.Branch(not_equal); 2359 exit.Branch(not_equal);
2346 2360
2347 // Rethrow exception. 2361 // Rethrow exception.
2348 frame_->EmitPush(eax); // undo pop from above 2362 frame_->EmitPush(eax); // undo pop from above
2349 frame_->CallRuntime(Runtime::kReThrow, 1); 2363 frame_->CallRuntime(Runtime::kReThrow, 1);
2350 2364
2351 // Done. 2365 // Done.
2352 exit.Bind(); 2366 exit.Bind();
2353 } 2367 }
2354 } 2368 }
2355 2369
2356 2370
2357 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2371 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2372 frame_->SpillAll();
2358 Comment cmnt(masm_, "[ DebuggerStatement"); 2373 Comment cmnt(masm_, "[ DebuggerStatement");
2359 RecordStatementPosition(node); 2374 RecordStatementPosition(node);
2360 frame_->CallRuntime(Runtime::kDebugBreak, 0); 2375 frame_->CallRuntime(Runtime::kDebugBreak, 0);
2361 // Ignore the return value. 2376 // Ignore the return value.
2362 } 2377 }
2363 2378
2364 2379
2365 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 2380 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
2366 ASSERT(boilerplate->IsBoilerplate()); 2381 ASSERT(boilerplate->IsBoilerplate());
2367 2382
2368 // Push the boilerplate on the stack. 2383 // Push the boilerplate on the stack.
2369 frame_->EmitPush(Immediate(boilerplate)); 2384 frame_->EmitPush(Immediate(boilerplate));
2370 2385
2371 // Create a new closure. 2386 // Create a new closure.
2372 frame_->EmitPush(esi); 2387 frame_->EmitPush(esi);
2373 frame_->CallRuntime(Runtime::kNewClosure, 2); 2388 frame_->CallRuntime(Runtime::kNewClosure, 2);
2374 frame_->EmitPush(eax); 2389 frame_->EmitPush(eax);
2375 } 2390 }
2376 2391
2377 2392
2378 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2393 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2394 frame_->SpillAll();
2379 Comment cmnt(masm_, "[ FunctionLiteral"); 2395 Comment cmnt(masm_, "[ FunctionLiteral");
2380 2396
2381 // Build the function boilerplate and instantiate it. 2397 // Build the function boilerplate and instantiate it.
2382 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 2398 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
2383 // Check for stack-overflow exception. 2399 // Check for stack-overflow exception.
2384 if (HasStackOverflow()) return; 2400 if (HasStackOverflow()) return;
2385 InstantiateBoilerplate(boilerplate); 2401 InstantiateBoilerplate(boilerplate);
2386 } 2402 }
2387 2403
2388 2404
2389 void CodeGenerator::VisitFunctionBoilerplateLiteral( 2405 void CodeGenerator::VisitFunctionBoilerplateLiteral(
2390 FunctionBoilerplateLiteral* node) { 2406 FunctionBoilerplateLiteral* node) {
2407 frame_->SpillAll();
2391 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 2408 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
2392 InstantiateBoilerplate(node->boilerplate()); 2409 InstantiateBoilerplate(node->boilerplate());
2393 } 2410 }
2394 2411
2395 2412
2396 void CodeGenerator::VisitConditional(Conditional* node) { 2413 void CodeGenerator::VisitConditional(Conditional* node) {
2414 frame_->SpillAll();
2397 Comment cmnt(masm_, "[ Conditional"); 2415 Comment cmnt(masm_, "[ Conditional");
2398 JumpTarget then(this); 2416 JumpTarget then(this);
2399 JumpTarget else_(this); 2417 JumpTarget else_(this);
2400 JumpTarget exit(this); 2418 JumpTarget exit(this);
2401 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 2419 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
2402 if (frame_ != NULL) { 2420 if (frame_ != NULL) {
2403 Branch(false, &else_); 2421 Branch(false, &else_);
2404 } 2422 }
2405 if (frame_ != NULL || then.is_linked()) { 2423 if (frame_ != NULL || then.is_linked()) {
2406 then.Bind(); 2424 then.Bind();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2447 exit.Bind(); 2465 exit.Bind();
2448 frame_->EmitPush(eax); 2466 frame_->EmitPush(eax);
2449 } else { 2467 } else {
2450 frame_->EmitPush(SlotOperand(slot, ecx)); 2468 frame_->EmitPush(SlotOperand(slot, ecx));
2451 } 2469 }
2452 } 2470 }
2453 } 2471 }
2454 2472
2455 2473
2456 void CodeGenerator::VisitSlot(Slot* node) { 2474 void CodeGenerator::VisitSlot(Slot* node) {
2475 frame_->SpillAll();
2457 Comment cmnt(masm_, "[ Slot"); 2476 Comment cmnt(masm_, "[ Slot");
2458 LoadFromSlot(node, typeof_state()); 2477 LoadFromSlot(node, typeof_state());
2459 } 2478 }
2460 2479
2461 2480
2462 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2481 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2482 frame_->SpillAll();
2463 Comment cmnt(masm_, "[ VariableProxy"); 2483 Comment cmnt(masm_, "[ VariableProxy");
2464 Variable* var = node->var(); 2484 Variable* var = node->var();
2465 Expression* expr = var->rewrite(); 2485 Expression* expr = var->rewrite();
2466 if (expr != NULL) { 2486 if (expr != NULL) {
2467 // We have to be wary of calling Visit directly on expressions. Because 2487 // We have to be wary of calling Visit directly on expressions. Because
2468 // of special casing comparisons of the form typeof<expr> === "string", 2488 // of special casing comparisons of the form typeof<expr> === "string",
2469 // we can return from a call from Visit (to a comparison or a unary 2489 // we can return from a call from Visit (to a comparison or a unary
2470 // operation) without a virtual frame; which will probably crash if we 2490 // operation) without a virtual frame; which will probably crash if we
2471 // try to emit frame code before reestablishing a frame. Here we're 2491 // try to emit frame code before reestablishing a frame. Here we're
2472 // safe as long as variable proxies can't rewrite into typeof 2492 // safe as long as variable proxies can't rewrite into typeof
2473 // comparisons or unary logical not expressions. 2493 // comparisons or unary logical not expressions.
2474 Visit(expr); 2494 Visit(expr);
2475 ASSERT(frame_ != NULL); 2495 ASSERT(frame_ != NULL);
2476 } else { 2496 } else {
2477 ASSERT(var->is_global()); 2497 ASSERT(var->is_global());
2478 Reference ref(this, node); 2498 Reference ref(this, node);
2479 ref.GetValue(typeof_state()); 2499 ref.GetValue(typeof_state());
2480 } 2500 }
2481 } 2501 }
2482 2502
2483 2503
2484 void CodeGenerator::VisitLiteral(Literal* node) { 2504 void CodeGenerator::VisitLiteral(Literal* node) {
2505 frame_->SpillAll();
2485 Comment cmnt(masm_, "[ Literal"); 2506 Comment cmnt(masm_, "[ Literal");
2486 if (node->handle()->IsSmi() && !IsInlineSmi(node)) { 2507 if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
2487 // To prevent long attacker-controlled byte sequences in code, larger 2508 // To prevent long attacker-controlled byte sequences in code, larger
2488 // Smis are loaded in two steps. 2509 // Smis are loaded in two steps.
2489 int bits = reinterpret_cast<int>(*node->handle()); 2510 int bits = reinterpret_cast<int>(*node->handle());
2490 __ mov(eax, bits & 0x0000FFFF); 2511 __ mov(eax, bits & 0x0000FFFF);
2491 __ xor_(eax, bits & 0xFFFF0000); 2512 __ xor_(eax, bits & 0xFFFF0000);
2492 frame_->EmitPush(eax); 2513 frame_->EmitPush(eax);
2493 } else { 2514 } else {
2494 frame_->EmitPush(Immediate(node->handle())); 2515 frame_->EmitPush(Immediate(node->handle()));
(...skipping 24 matching lines...) Expand all
2519 // RegExp pattern (2). 2540 // RegExp pattern (2).
2520 __ push(Immediate(node_->pattern())); 2541 __ push(Immediate(node_->pattern()));
2521 // RegExp flags (3). 2542 // RegExp flags (3).
2522 __ push(Immediate(node_->flags())); 2543 __ push(Immediate(node_->flags()));
2523 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 2544 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
2524 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx 2545 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx
2525 } 2546 }
2526 2547
2527 2548
2528 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2549 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
2550 frame_->SpillAll();
2529 Comment cmnt(masm_, "[ RegExp Literal"); 2551 Comment cmnt(masm_, "[ RegExp Literal");
2530 RegExpDeferred* deferred = new RegExpDeferred(this, node); 2552 RegExpDeferred* deferred = new RegExpDeferred(this, node);
2531 2553
2532 // Retrieve the literal array and check the allocated entry. 2554 // Retrieve the literal array and check the allocated entry.
2533 2555
2534 // Load the function of this activation. 2556 // Load the function of this activation.
2535 __ mov(ecx, frame_->Function()); 2557 __ mov(ecx, frame_->Function());
2536 2558
2537 // Load the literals array of the function. 2559 // Load the literals array of the function.
2538 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2560 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2579 // Literal index (1). 2601 // Literal index (1).
2580 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2602 __ push(Immediate(Smi::FromInt(node_->literal_index())));
2581 // Constant properties (2). 2603 // Constant properties (2).
2582 __ push(Immediate(node_->constant_properties())); 2604 __ push(Immediate(node_->constant_properties()));
2583 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 2605 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
2584 __ mov(ebx, Operand(eax)); 2606 __ mov(ebx, Operand(eax));
2585 } 2607 }
2586 2608
2587 2609
2588 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2610 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2611 frame_->SpillAll();
2589 Comment cmnt(masm_, "[ ObjectLiteral"); 2612 Comment cmnt(masm_, "[ ObjectLiteral");
2590 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 2613 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
2591 2614
2592 // Retrieve the literal array and check the allocated entry. 2615 // Retrieve the literal array and check the allocated entry.
2593 2616
2594 // Load the function of this activation. 2617 // Load the function of this activation.
2595 __ mov(ecx, frame_->Function()); 2618 __ mov(ecx, frame_->Function());
2596 2619
2597 // Load the literals array of the function. 2620 // Load the literals array of the function.
2598 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2621 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
(...skipping 21 matching lines...) Expand all
2620 ObjectLiteral::Property* property = node->properties()->at(i); 2643 ObjectLiteral::Property* property = node->properties()->at(i);
2621 switch (property->kind()) { 2644 switch (property->kind()) {
2622 case ObjectLiteral::Property::CONSTANT: break; 2645 case ObjectLiteral::Property::CONSTANT: break;
2623 case ObjectLiteral::Property::COMPUTED: { 2646 case ObjectLiteral::Property::COMPUTED: {
2624 Handle<Object> key(property->key()->handle()); 2647 Handle<Object> key(property->key()->handle());
2625 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2648 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2626 if (key->IsSymbol()) { 2649 if (key->IsSymbol()) {
2627 __ mov(eax, frame_->Top()); 2650 __ mov(eax, frame_->Top());
2628 frame_->EmitPush(eax); 2651 frame_->EmitPush(eax);
2629 Load(property->value()); 2652 Load(property->value());
2630 frame_->Pop(eax); 2653 frame_->EmitPop(eax);
2631 __ Set(ecx, Immediate(key)); 2654 __ Set(ecx, Immediate(key));
2632 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 2655 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
2633 frame_->Drop(); 2656 frame_->Drop();
2634 // Ignore result. 2657 // Ignore result.
2635 break; 2658 break;
2636 } 2659 }
2637 // Fall through 2660 // Fall through
2638 } 2661 }
2639 case ObjectLiteral::Property::PROTOTYPE: { 2662 case ObjectLiteral::Property::PROTOTYPE: {
2640 __ mov(eax, frame_->Top()); 2663 __ mov(eax, frame_->Top());
(...skipping 28 matching lines...) Expand all
2669 // Ignore result. 2692 // Ignore result.
2670 break; 2693 break;
2671 } 2694 }
2672 default: UNREACHABLE(); 2695 default: UNREACHABLE();
2673 } 2696 }
2674 } 2697 }
2675 } 2698 }
2676 2699
2677 2700
2678 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2701 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2702 frame_->SpillAll();
2679 Comment cmnt(masm_, "[ ArrayLiteral"); 2703 Comment cmnt(masm_, "[ ArrayLiteral");
2680 2704
2681 // Call runtime to create the array literal. 2705 // Call runtime to create the array literal.
2682 frame_->EmitPush(Immediate(node->literals())); 2706 frame_->EmitPush(Immediate(node->literals()));
2683 // Load the function of this frame. 2707 // Load the function of this frame.
2684 __ mov(ecx, frame_->Function()); 2708 __ mov(ecx, frame_->Function());
2685 // Load the literals array of the function. 2709 // Load the literals array of the function.
2686 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2710 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2687 frame_->EmitPush(ecx); 2711 frame_->EmitPush(ecx);
2688 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2); 2712 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2);
2689 2713
2690 // Push the resulting array literal on the stack. 2714 // Push the resulting array literal on the stack.
2691 frame_->EmitPush(eax); 2715 frame_->EmitPush(eax);
2692 2716
2693 // Generate code to set the elements in the array that are not 2717 // Generate code to set the elements in the array that are not
2694 // literals. 2718 // literals.
2695 for (int i = 0; i < node->values()->length(); i++) { 2719 for (int i = 0; i < node->values()->length(); i++) {
2696 Expression* value = node->values()->at(i); 2720 Expression* value = node->values()->at(i);
2697 2721
2698 // If value is literal the property value is already 2722 // If value is literal the property value is already
2699 // set in the boilerplate object. 2723 // set in the boilerplate object.
2700 if (value->AsLiteral() == NULL) { 2724 if (value->AsLiteral() == NULL) {
2701 // The property must be set by generated code. 2725 // The property must be set by generated code.
2702 Load(value); 2726 Load(value);
2703 2727
2704 // Get the value off the stack. 2728 // Get the value off the stack.
2705 frame_->Pop(eax); 2729 frame_->EmitPop(eax);
2706 // Fetch the object literal while leaving on the stack. 2730 // Fetch the object literal while leaving on the stack.
2707 __ mov(ecx, frame_->Top()); 2731 __ mov(ecx, frame_->Top());
2708 // Get the elements array. 2732 // Get the elements array.
2709 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); 2733 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
2710 2734
2711 // Write to the indexed properties array. 2735 // Write to the indexed properties array.
2712 int offset = i * kPointerSize + Array::kHeaderSize; 2736 int offset = i * kPointerSize + Array::kHeaderSize;
2713 __ mov(FieldOperand(ecx, offset), eax); 2737 __ mov(FieldOperand(ecx, offset), eax);
2714 2738
2715 // Update the write barrier for the array address. 2739 // Update the write barrier for the array address.
2716 __ RecordWrite(ecx, offset, eax, ebx); 2740 __ RecordWrite(ecx, offset, eax, ebx);
2717 } 2741 }
2718 } 2742 }
2719 } 2743 }
2720 2744
2721 2745
2722 bool CodeGenerator::IsInlineSmi(Literal* literal) { 2746 bool CodeGenerator::IsInlineSmi(Literal* literal) {
2723 if (literal == NULL || !literal->handle()->IsSmi()) return false; 2747 if (literal == NULL || !literal->handle()->IsSmi()) return false;
2724 int int_value = Smi::cast(*literal->handle())->value(); 2748 int int_value = Smi::cast(*literal->handle())->value();
2725 return is_intn(int_value, kMaxSmiInlinedBits); 2749 return is_intn(int_value, kMaxSmiInlinedBits);
2726 } 2750 }
2727 2751
2728 2752
2729 void CodeGenerator::VisitAssignment(Assignment* node) { 2753 void CodeGenerator::VisitAssignment(Assignment* node) {
2754 frame_->SpillAll();
2730 Comment cmnt(masm_, "[ Assignment"); 2755 Comment cmnt(masm_, "[ Assignment");
2731 2756
2732 RecordStatementPosition(node); 2757 RecordStatementPosition(node);
2733 { Reference target(this, node->target()); 2758 { Reference target(this, node->target());
2734 if (target.is_illegal()) { 2759 if (target.is_illegal()) {
2735 // Fool the virtual frame into thinking that we left the assignment's 2760 // Fool the virtual frame into thinking that we left the assignment's
2736 // value on the frame. 2761 // value on the frame.
2737 frame_->EmitPush(Immediate(Smi::FromInt(0))); 2762 frame_->EmitPush(Immediate(Smi::FromInt(0)));
2738 return; 2763 return;
2739 } 2764 }
(...skipping 29 matching lines...) Expand all
2769 target.SetValue(CONST_INIT); 2794 target.SetValue(CONST_INIT);
2770 } else { 2795 } else {
2771 target.SetValue(NOT_CONST_INIT); 2796 target.SetValue(NOT_CONST_INIT);
2772 } 2797 }
2773 } 2798 }
2774 } 2799 }
2775 } 2800 }
2776 2801
2777 2802
2778 void CodeGenerator::VisitThrow(Throw* node) { 2803 void CodeGenerator::VisitThrow(Throw* node) {
2804 frame_->SpillAll();
2779 Comment cmnt(masm_, "[ Throw"); 2805 Comment cmnt(masm_, "[ Throw");
2780 2806
2781 Load(node->exception()); 2807 Load(node->exception());
2782 __ RecordPosition(node->position()); 2808 __ RecordPosition(node->position());
2783 frame_->CallRuntime(Runtime::kThrow, 1); 2809 frame_->CallRuntime(Runtime::kThrow, 1);
2784 frame_->EmitPush(eax); 2810 frame_->EmitPush(eax);
2785 } 2811 }
2786 2812
2787 2813
2788 void CodeGenerator::VisitProperty(Property* node) { 2814 void CodeGenerator::VisitProperty(Property* node) {
2815 frame_->SpillAll();
2789 Comment cmnt(masm_, "[ Property"); 2816 Comment cmnt(masm_, "[ Property");
2790 Reference property(this, node); 2817 Reference property(this, node);
2791 property.GetValue(typeof_state()); 2818 property.GetValue(typeof_state());
2792 } 2819 }
2793 2820
2794 2821
2795 void CodeGenerator::VisitCall(Call* node) { 2822 void CodeGenerator::VisitCall(Call* node) {
2823 frame_->SpillAll();
2796 Comment cmnt(masm_, "[ Call"); 2824 Comment cmnt(masm_, "[ Call");
2797 2825
2798 ZoneList<Expression*>* args = node->arguments(); 2826 ZoneList<Expression*>* args = node->arguments();
2799 2827
2800 RecordStatementPosition(node); 2828 RecordStatementPosition(node);
2801 2829
2802 // Check if the function is a variable or a property. 2830 // Check if the function is a variable or a property.
2803 Expression* function = node->expression(); 2831 Expression* function = node->expression();
2804 Variable* var = function->AsVariableProxy()->AsVariable(); 2832 Variable* var = function->AsVariableProxy()->AsVariable();
2805 Property* property = function->AsProperty(); 2833 Property* property = function->AsProperty();
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
2917 // Pass the global proxy as the receiver. 2945 // Pass the global proxy as the receiver.
2918 LoadGlobalReceiver(eax); 2946 LoadGlobalReceiver(eax);
2919 2947
2920 // Call the function. 2948 // Call the function.
2921 CallWithArguments(args, node->position()); 2949 CallWithArguments(args, node->position());
2922 } 2950 }
2923 } 2951 }
2924 2952
2925 2953
2926 void CodeGenerator::VisitCallNew(CallNew* node) { 2954 void CodeGenerator::VisitCallNew(CallNew* node) {
2955 frame_->SpillAll();
2927 Comment cmnt(masm_, "[ CallNew"); 2956 Comment cmnt(masm_, "[ CallNew");
2928 2957
2929 // According to ECMA-262, section 11.2.2, page 44, the function 2958 // According to ECMA-262, section 11.2.2, page 44, the function
2930 // expression in new calls must be evaluated before the 2959 // expression in new calls must be evaluated before the
2931 // arguments. This is different from ordinary calls, where the 2960 // arguments. This is different from ordinary calls, where the
2932 // actual function to call is resolved after the arguments have been 2961 // actual function to call is resolved after the arguments have been
2933 // evaluated. 2962 // evaluated.
2934 2963
2935 // Compute function to call and use the global object as the 2964 // Compute function to call and use the global object as the
2936 // receiver. There is no need to use the global proxy here because 2965 // receiver. There is no need to use the global proxy here because
(...skipping 23 matching lines...) Expand all
2960 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 2989 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
2961 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1); 2990 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
2962 // Discard the function and "push" the newly created object. 2991 // Discard the function and "push" the newly created object.
2963 __ mov(frame_->Top(), eax); 2992 __ mov(frame_->Top(), eax);
2964 } 2993 }
2965 2994
2966 2995
2967 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 2996 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
2968 ASSERT(args->length() == 1); 2997 ASSERT(args->length() == 1);
2969 Load(args->at(0)); 2998 Load(args->at(0));
2970 frame_->Pop(eax); 2999 frame_->EmitPop(eax);
2971 __ test(eax, Immediate(kSmiTagMask)); 3000 __ test(eax, Immediate(kSmiTagMask));
2972 cc_reg_ = zero; 3001 cc_reg_ = zero;
2973 } 3002 }
2974 3003
2975 3004
2976 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3005 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
2977 ASSERT(args->length() == 1); 3006 ASSERT(args->length() == 1);
2978 Load(args->at(0)); 3007 Load(args->at(0));
2979 frame_->Pop(eax); 3008 frame_->EmitPop(eax);
2980 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 3009 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
2981 cc_reg_ = zero; 3010 cc_reg_ = zero;
2982 } 3011 }
2983 3012
2984 3013
2985 // This generates code that performs a charCodeAt() call or returns 3014 // This generates code that performs a charCodeAt() call or returns
2986 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3015 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
2987 // It can handle flat and sliced strings, 8 and 16 bit characters and 3016 // It can handle flat and sliced strings, 8 and 16 bit characters and
2988 // cons strings where the answer is found in the left hand branch of the 3017 // cons strings where the answer is found in the left hand branch of the
2989 // cons. The slow case will flatten the string, which will ensure that 3018 // cons. The slow case will flatten the string, which will ensure that
2990 // the answer is in the left hand side the next time around. 3019 // the answer is in the left hand side the next time around.
2991 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3020 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
2992 ASSERT(args->length() == 2); 3021 ASSERT(args->length() == 2);
2993 3022
2994 JumpTarget slow_case(this); 3023 JumpTarget slow_case(this);
2995 JumpTarget end(this); 3024 JumpTarget end(this);
2996 JumpTarget not_a_flat_string(this); 3025 JumpTarget not_a_flat_string(this);
2997 JumpTarget not_a_cons_string_either(this); 3026 JumpTarget not_a_cons_string_either(this);
2998 JumpTarget try_again_with_new_string(this); 3027 JumpTarget try_again_with_new_string(this);
2999 JumpTarget ascii_string(this); 3028 JumpTarget ascii_string(this);
3000 JumpTarget got_char_code(this); 3029 JumpTarget got_char_code(this);
3001 3030
3002 // Load the string into eax. 3031 // Load the string into eax.
3003 Load(args->at(0)); 3032 Load(args->at(0));
3004 frame_->Pop(eax); 3033 frame_->EmitPop(eax);
3005 // If the receiver is a smi return undefined. 3034 // If the receiver is a smi return undefined.
3006 ASSERT(kSmiTag == 0); 3035 ASSERT(kSmiTag == 0);
3007 __ test(eax, Immediate(kSmiTagMask)); 3036 __ test(eax, Immediate(kSmiTagMask));
3008 slow_case.Branch(zero, not_taken); 3037 slow_case.Branch(zero, not_taken);
3009 3038
3010 // Load the index into ebx. 3039 // Load the index into ebx.
3011 Load(args->at(1)); 3040 Load(args->at(1));
3012 frame_->Pop(ebx); 3041 frame_->EmitPop(ebx);
3013 3042
3014 // Check for negative or non-smi index. 3043 // Check for negative or non-smi index.
3015 ASSERT(kSmiTag == 0); 3044 ASSERT(kSmiTag == 0);
3016 __ test(ebx, Immediate(kSmiTagMask | 0x80000000)); 3045 __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
3017 slow_case.Branch(not_zero, not_taken); 3046 slow_case.Branch(not_zero, not_taken);
3018 // Get rid of the smi tag on the index. 3047 // Get rid of the smi tag on the index.
3019 __ sar(ebx, kSmiTagSize); 3048 __ sar(ebx, kSmiTagSize);
3020 3049
3021 try_again_with_new_string.Bind(); 3050 try_again_with_new_string.Bind();
3022 // Get the type of the heap object into edi. 3051 // Get the type of the heap object into edi.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3102 3131
3103 3132
3104 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3133 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3105 ASSERT(args->length() == 1); 3134 ASSERT(args->length() == 1);
3106 Load(args->at(0)); 3135 Load(args->at(0));
3107 JumpTarget answer(this); 3136 JumpTarget answer(this);
3108 // We need the CC bits to come out as not_equal in the case where the 3137 // We need the CC bits to come out as not_equal in the case where the
3109 // object is a smi. This can't be done with the usual test opcode so 3138 // object is a smi. This can't be done with the usual test opcode so
3110 // we copy the object to ecx and do some destructive ops on it that 3139 // we copy the object to ecx and do some destructive ops on it that
3111 // result in the right CC bits. 3140 // result in the right CC bits.
3112 frame_->Pop(eax); 3141 frame_->EmitPop(eax);
3113 __ mov(ecx, Operand(eax)); 3142 __ mov(ecx, Operand(eax));
3114 __ and_(ecx, kSmiTagMask); 3143 __ and_(ecx, kSmiTagMask);
3115 __ xor_(ecx, kSmiTagMask); 3144 __ xor_(ecx, kSmiTagMask);
3116 answer.Branch(not_equal, not_taken); 3145 answer.Branch(not_equal, not_taken);
3117 // It is a heap object - get map. 3146 // It is a heap object - get map.
3118 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 3147 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
3119 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); 3148 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
3120 // Check if the object is a JS array or not. 3149 // Check if the object is a JS array or not.
3121 __ cmp(eax, JS_ARRAY_TYPE); 3150 __ cmp(eax, JS_ARRAY_TYPE);
3122 answer.Bind(); 3151 answer.Bind();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
3201 __ mov(frame_->Top(), eax); 3230 __ mov(frame_->Top(), eax);
3202 } 3231 }
3203 3232
3204 3233
3205 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 3234 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
3206 ASSERT(args->length() == 2); 3235 ASSERT(args->length() == 2);
3207 3236
3208 // Load the two objects into registers and perform the comparison. 3237 // Load the two objects into registers and perform the comparison.
3209 Load(args->at(0)); 3238 Load(args->at(0));
3210 Load(args->at(1)); 3239 Load(args->at(1));
3211 frame_->Pop(eax); 3240 frame_->EmitPop(eax);
3212 frame_->Pop(ecx); 3241 frame_->EmitPop(ecx);
3213 __ cmp(eax, Operand(ecx)); 3242 __ cmp(eax, Operand(ecx));
3214 cc_reg_ = equal; 3243 cc_reg_ = equal;
3215 } 3244 }
3216 3245
3217 3246
3218 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 3247 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
3248 frame_->SpillAll();
3219 if (CheckForInlineRuntimeCall(node)) { 3249 if (CheckForInlineRuntimeCall(node)) {
3220 return; 3250 return;
3221 } 3251 }
3222 3252
3223 ZoneList<Expression*>* args = node->arguments(); 3253 ZoneList<Expression*>* args = node->arguments();
3224 Comment cmnt(masm_, "[ CallRuntime"); 3254 Comment cmnt(masm_, "[ CallRuntime");
3225 Runtime::Function* function = node->function(); 3255 Runtime::Function* function = node->function();
3226 3256
3227 if (function == NULL) { 3257 if (function == NULL) {
3228 // Prepare stack for calling JS runtime function. 3258 // Prepare stack for calling JS runtime function.
(...skipping 18 matching lines...) Expand all
3247 __ mov(frame_->Top(), eax); 3277 __ mov(frame_->Top(), eax);
3248 } else { 3278 } else {
3249 // Call the C runtime function. 3279 // Call the C runtime function.
3250 frame_->CallRuntime(function, arg_count); 3280 frame_->CallRuntime(function, arg_count);
3251 frame_->EmitPush(eax); 3281 frame_->EmitPush(eax);
3252 } 3282 }
3253 } 3283 }
3254 3284
3255 3285
3256 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 3286 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
3287 frame_->SpillAll();
3257 // Note that because of NOT and an optimization in comparison of a typeof 3288 // 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 3289 // expression to a literal string, this function can fail to leave a value
3259 // on top of the frame or in the cc register. 3290 // on top of the frame or in the cc register.
3260 Comment cmnt(masm_, "[ UnaryOperation"); 3291 Comment cmnt(masm_, "[ UnaryOperation");
3261 3292
3262 Token::Value op = node->op(); 3293 Token::Value op = node->op();
3263 3294
3264 if (op == Token::NOT) { 3295 if (op == Token::NOT) {
3265 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF, 3296 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
3266 false_target(), true_target(), true); 3297 false_target(), true_target(), true);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3321 switch (op) { 3352 switch (op) {
3322 case Token::NOT: 3353 case Token::NOT:
3323 case Token::DELETE: 3354 case Token::DELETE:
3324 case Token::TYPEOF: 3355 case Token::TYPEOF:
3325 UNREACHABLE(); // handled above 3356 UNREACHABLE(); // handled above
3326 break; 3357 break;
3327 3358
3328 case Token::SUB: { 3359 case Token::SUB: {
3329 UnarySubStub stub; 3360 UnarySubStub stub;
3330 // TODO(1222589): remove dependency of TOS being cached inside stub 3361 // TODO(1222589): remove dependency of TOS being cached inside stub
3331 frame_->Pop(eax); 3362 frame_->EmitPop(eax);
3332 frame_->CallStub(&stub, 0); 3363 frame_->CallStub(&stub, 0);
3333 frame_->EmitPush(eax); 3364 frame_->EmitPush(eax);
3334 break; 3365 break;
3335 } 3366 }
3336 3367
3337 case Token::BIT_NOT: { 3368 case Token::BIT_NOT: {
3338 // Smi check. 3369 // Smi check.
3339 JumpTarget smi_label(this); 3370 JumpTarget smi_label(this);
3340 JumpTarget continue_label(this); 3371 JumpTarget continue_label(this);
3341 frame_->Pop(eax); 3372 frame_->EmitPop(eax);
3342 __ test(eax, Immediate(kSmiTagMask)); 3373 __ test(eax, Immediate(kSmiTagMask));
3343 smi_label.Branch(zero, taken); 3374 smi_label.Branch(zero, taken);
3344 3375
3345 frame_->EmitPush(eax); // undo popping of TOS 3376 frame_->EmitPush(eax); // undo popping of TOS
3346 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_FUNCTION, 1); 3377 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_FUNCTION, 1);
3347 3378
3348 continue_label.Jump(); 3379 continue_label.Jump();
3349 smi_label.Bind(); 3380 smi_label.Bind();
3350 __ not_(eax); 3381 __ not_(eax);
3351 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag. 3382 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag.
3352 continue_label.Bind(); 3383 continue_label.Bind();
3353 frame_->EmitPush(eax); 3384 frame_->EmitPush(eax);
3354 break; 3385 break;
3355 } 3386 }
3356 3387
3357 case Token::VOID: 3388 case Token::VOID:
3358 __ mov(frame_->Top(), Factory::undefined_value()); 3389 __ mov(frame_->Top(), Factory::undefined_value());
3359 break; 3390 break;
3360 3391
3361 case Token::ADD: { 3392 case Token::ADD: {
3362 // Smi check. 3393 // Smi check.
3363 JumpTarget continue_label(this); 3394 JumpTarget continue_label(this);
3364 frame_->Pop(eax); 3395 frame_->EmitPop(eax);
3365 __ test(eax, Immediate(kSmiTagMask)); 3396 __ test(eax, Immediate(kSmiTagMask));
3366 continue_label.Branch(zero); 3397 continue_label.Branch(zero);
3367 3398
3368 frame_->EmitPush(eax); 3399 frame_->EmitPush(eax);
3369 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1); 3400 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1);
3370 3401
3371 continue_label.Bind(); 3402 continue_label.Bind();
3372 frame_->EmitPush(eax); 3403 frame_->EmitPush(eax);
3373 break; 3404 break;
3374 } 3405 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
3459 if (is_postfix_) { 3490 if (is_postfix_) {
3460 RevertToNumberStub to_number_stub(is_increment_); 3491 RevertToNumberStub to_number_stub(is_increment_);
3461 __ CallStub(&to_number_stub); 3492 __ CallStub(&to_number_stub);
3462 } 3493 }
3463 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); 3494 CounterOpStub stub(result_offset_, is_postfix_, is_increment_);
3464 __ CallStub(&stub); 3495 __ CallStub(&stub);
3465 } 3496 }
3466 3497
3467 3498
3468 void CodeGenerator::VisitCountOperation(CountOperation* node) { 3499 void CodeGenerator::VisitCountOperation(CountOperation* node) {
3500 frame_->SpillAll();
3469 Comment cmnt(masm_, "[ CountOperation"); 3501 Comment cmnt(masm_, "[ CountOperation");
3470 3502
3471 bool is_postfix = node->is_postfix(); 3503 bool is_postfix = node->is_postfix();
3472 bool is_increment = node->op() == Token::INC; 3504 bool is_increment = node->op() == Token::INC;
3473 3505
3474 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 3506 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3475 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3507 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3476 3508
3477 // Postfix: Make room for the result. 3509 // Postfix: Make room for the result.
3478 if (is_postfix) { 3510 if (is_postfix) {
3479 frame_->EmitPush(Immediate(0)); 3511 frame_->EmitPush(Immediate(0));
3480 } 3512 }
3481 3513
3482 { Reference target(this, node->expression()); 3514 { Reference target(this, node->expression());
3483 if (target.is_illegal()) { 3515 if (target.is_illegal()) {
3484 // Spoof the virtual frame to have the expected height (one higher 3516 // Spoof the virtual frame to have the expected height (one higher
3485 // than on entry). 3517 // than on entry).
3486 if (!is_postfix) { 3518 if (!is_postfix) {
3487 frame_->EmitPush(Immediate(Smi::FromInt(0))); 3519 frame_->EmitPush(Immediate(Smi::FromInt(0)));
3488 } 3520 }
3489 return; 3521 return;
3490 } 3522 }
3491 target.GetValue(NOT_INSIDE_TYPEOF); 3523 target.GetValue(NOT_INSIDE_TYPEOF);
3492 3524
3493 CountOperationDeferred* deferred = 3525 CountOperationDeferred* deferred =
3494 new CountOperationDeferred(this, is_postfix, is_increment, 3526 new CountOperationDeferred(this, is_postfix, is_increment,
3495 target.size() * kPointerSize); 3527 target.size() * kPointerSize);
3496 3528
3497 frame_->Pop(eax); // Load TOS into eax for calculations below 3529 frame_->EmitPop(eax); // Load TOS into eax for calculations below
3498 3530
3499 // Postfix: Store the old value as the result. 3531 // Postfix: Store the old value as the result.
3500 if (is_postfix) { 3532 if (is_postfix) {
3501 __ mov(frame_->ElementAt(target.size()), eax); 3533 __ mov(frame_->ElementAt(target.size()), eax);
3502 } 3534 }
3503 3535
3504 // Perform optimistic increment/decrement. 3536 // Perform optimistic increment/decrement.
3505 if (is_increment) { 3537 if (is_increment) {
3506 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3538 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3507 } else { 3539 } else {
(...skipping 14 matching lines...) Expand all
3522 } 3554 }
3523 3555
3524 // Postfix: Discard the new value and use the old. 3556 // Postfix: Discard the new value and use the old.
3525 if (is_postfix) { 3557 if (is_postfix) {
3526 frame_->Drop(); 3558 frame_->Drop();
3527 } 3559 }
3528 } 3560 }
3529 3561
3530 3562
3531 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 3563 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
3564 frame_->SpillAll();
3532 // Note that due to an optimization in comparison operations (typeof 3565 // Note that due to an optimization in comparison operations (typeof
3533 // compared to a string literal), we can evaluate a binary expression such 3566 // compared to a string literal), we can evaluate a binary expression such
3534 // as AND or OR and not leave a value on the frame or in the cc register. 3567 // as AND or OR and not leave a value on the frame or in the cc register.
3535 Comment cmnt(masm_, "[ BinaryOperation"); 3568 Comment cmnt(masm_, "[ BinaryOperation");
3536 Token::Value op = node->op(); 3569 Token::Value op = node->op();
3537 3570
3538 // According to ECMA-262 section 11.11, page 58, the binary logical 3571 // According to ECMA-262 section 11.11, page 58, the binary logical
3539 // operators must yield the result of one of the two expressions 3572 // operators must yield the result of one of the two expressions
3540 // before any ToBoolean() conversions. This means that the value 3573 // before any ToBoolean() conversions. This means that the value
3541 // produced by a && or || operator is not necessarily a boolean. 3574 // produced by a && or || operator is not necessarily a boolean.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
3661 } else { 3694 } else {
3662 Load(node->left()); 3695 Load(node->left());
3663 Load(node->right()); 3696 Load(node->right());
3664 GenericBinaryOperation(node->op(), node->type(), overwrite_mode); 3697 GenericBinaryOperation(node->op(), node->type(), overwrite_mode);
3665 } 3698 }
3666 } 3699 }
3667 } 3700 }
3668 3701
3669 3702
3670 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3703 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3704 frame_->SpillAll();
3671 frame_->EmitPush(frame_->Function()); 3705 frame_->EmitPush(frame_->Function());
3672 } 3706 }
3673 3707
3674 3708
3675 class InstanceofStub: public CodeStub { 3709 class InstanceofStub: public CodeStub {
3676 public: 3710 public:
3677 InstanceofStub() { } 3711 InstanceofStub() { }
3678 3712
3679 void Generate(MacroAssembler* masm); 3713 void Generate(MacroAssembler* masm);
3680 3714
3681 private: 3715 private:
3682 Major MajorKey() { return Instanceof; } 3716 Major MajorKey() { return Instanceof; }
3683 int MinorKey() { return 0; } 3717 int MinorKey() { return 0; }
3684 }; 3718 };
3685 3719
3686 3720
3687 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 3721 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
3722 frame_->SpillAll();
3688 Comment cmnt(masm_, "[ CompareOperation"); 3723 Comment cmnt(masm_, "[ CompareOperation");
3689 3724
3690 // Get the expressions from the node. 3725 // Get the expressions from the node.
3691 Expression* left = node->left(); 3726 Expression* left = node->left();
3692 Expression* right = node->right(); 3727 Expression* right = node->right();
3693 Token::Value op = node->op(); 3728 Token::Value op = node->op();
3694 3729
3695 // To make null checks efficient, we check if either left or right is the 3730 // To make null checks efficient, we check if either left or right is the
3696 // literal 'null'. If so, we optimize the code by inlining a null check 3731 // literal 'null'. If so, we optimize the code by inlining a null check
3697 // instead of calling the (very) general runtime routine for checking 3732 // instead of calling the (very) general runtime routine for checking
3698 // equality. 3733 // equality.
3699 if (op == Token::EQ || op == Token::EQ_STRICT) { 3734 if (op == Token::EQ || op == Token::EQ_STRICT) {
3700 bool left_is_null = 3735 bool left_is_null =
3701 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 3736 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
3702 bool right_is_null = 3737 bool right_is_null =
3703 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 3738 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
3704 // The 'null' value can only be equal to 'null' or 'undefined'. 3739 // The 'null' value can only be equal to 'null' or 'undefined'.
3705 if (left_is_null || right_is_null) { 3740 if (left_is_null || right_is_null) {
3706 Load(left_is_null ? right : left); 3741 Load(left_is_null ? right : left);
3707 frame_->Pop(eax); 3742 frame_->EmitPop(eax);
3708 __ cmp(eax, Factory::null_value()); 3743 __ cmp(eax, Factory::null_value());
3709 3744
3710 // The 'null' value is only equal to 'undefined' if using non-strict 3745 // The 'null' value is only equal to 'undefined' if using non-strict
3711 // comparisons. 3746 // comparisons.
3712 if (op != Token::EQ_STRICT) { 3747 if (op != Token::EQ_STRICT) {
3713 true_target()->Branch(equal); 3748 true_target()->Branch(equal);
3714 3749
3715 __ cmp(eax, Factory::undefined_value()); 3750 __ cmp(eax, Factory::undefined_value());
3716 true_target()->Branch(equal); 3751 true_target()->Branch(equal);
3717 3752
(...skipping 17 matching lines...) Expand all
3735 // 'typeof <expression> == <string>'. 3770 // 'typeof <expression> == <string>'.
3736 UnaryOperation* operation = left->AsUnaryOperation(); 3771 UnaryOperation* operation = left->AsUnaryOperation();
3737 if ((op == Token::EQ || op == Token::EQ_STRICT) && 3772 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
3738 (operation != NULL && operation->op() == Token::TYPEOF) && 3773 (operation != NULL && operation->op() == Token::TYPEOF) &&
3739 (right->AsLiteral() != NULL && 3774 (right->AsLiteral() != NULL &&
3740 right->AsLiteral()->handle()->IsString())) { 3775 right->AsLiteral()->handle()->IsString())) {
3741 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 3776 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
3742 3777
3743 // Load the operand and move it to register edx. 3778 // Load the operand and move it to register edx.
3744 LoadTypeofExpression(operation->expression()); 3779 LoadTypeofExpression(operation->expression());
3745 frame_->Pop(edx); 3780 frame_->EmitPop(edx);
3746 3781
3747 if (check->Equals(Heap::number_symbol())) { 3782 if (check->Equals(Heap::number_symbol())) {
3748 __ test(edx, Immediate(kSmiTagMask)); 3783 __ test(edx, Immediate(kSmiTagMask));
3749 true_target()->Branch(zero); 3784 true_target()->Branch(zero);
3750 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 3785 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
3751 __ cmp(edx, Factory::heap_number_map()); 3786 __ cmp(edx, Factory::heap_number_map());
3752 cc_reg_ = equal; 3787 cc_reg_ = equal;
3753 3788
3754 } else if (check->Equals(Heap::string_symbol())) { 3789 } else if (check->Equals(Heap::string_symbol())) {
3755 __ test(edx, Immediate(kSmiTagMask)); 3790 __ test(edx, Immediate(kSmiTagMask));
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
4044 } 4079 }
4045 4080
4046 // We must execute the store. Storing a variable must keep the 4081 // We must execute the store. Storing a variable must keep the
4047 // (new) value on the stack. This is necessary for compiling 4082 // (new) value on the stack. This is necessary for compiling
4048 // assignment expressions. 4083 // assignment expressions.
4049 // 4084 //
4050 // Note: We will reach here even with slot->var()->mode() == 4085 // Note: We will reach here even with slot->var()->mode() ==
4051 // Variable::CONST because of const declarations which will 4086 // Variable::CONST because of const declarations which will
4052 // initialize consts to 'the hole' value and by doing so, end up 4087 // initialize consts to 'the hole' value and by doing so, end up
4053 // calling this code. 4088 // calling this code.
4054 frame->Pop(eax); 4089 frame->EmitPop(eax);
4055 __ mov(cgen_->SlotOperand(slot, ecx), eax); 4090 __ mov(cgen_->SlotOperand(slot, ecx), eax);
4056 frame->EmitPush(eax); // RecordWrite may destroy the value in eax. 4091 frame->EmitPush(eax); // RecordWrite may destroy the value in eax.
4057 if (slot->type() == Slot::CONTEXT) { 4092 if (slot->type() == Slot::CONTEXT) {
4058 // ecx is loaded with context when calling SlotOperand above. 4093 // ecx is loaded with context when calling SlotOperand above.
4059 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 4094 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
4060 __ RecordWrite(ecx, offset, eax, ebx); 4095 __ RecordWrite(ecx, offset, eax, ebx);
4061 } 4096 }
4062 // If we definitely did not jump over the assignment, we do not need 4097 // If we definitely did not jump over the assignment, we do not need
4063 // to bind the exit label. Doing so can defeat peephole 4098 // to bind the exit label. Doing so can defeat peephole
4064 // optimization. 4099 // optimization.
4065 if (init_state == CONST_INIT) { 4100 if (init_state == CONST_INIT) {
4066 exit.Bind(); 4101 exit.Bind();
4067 } 4102 }
4068 } 4103 }
4069 break; 4104 break;
4070 } 4105 }
4071 4106
4072 case NAMED: { 4107 case NAMED: {
4073 Comment cmnt(masm, "[ Store to named Property"); 4108 Comment cmnt(masm, "[ Store to named Property");
4074 // Call the appropriate IC code. 4109 // Call the appropriate IC code.
4075 Handle<String> name(GetName()); 4110 Handle<String> name(GetName());
4076 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 4111 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
4077 // TODO(1222589): Make the IC grab the values from the stack. 4112 // TODO(1222589): Make the IC grab the values from the stack.
4078 frame->Pop(eax); 4113 frame->EmitPop(eax);
4079 // Setup the name register. 4114 // Setup the name register.
4080 __ mov(ecx, name); 4115 __ mov(ecx, name);
4081 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4116 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4082 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4117 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4083 break; 4118 break;
4084 } 4119 }
4085 4120
4086 case KEYED: { 4121 case KEYED: {
4087 Comment cmnt(masm, "[ Store to keyed Property"); 4122 Comment cmnt(masm, "[ Store to keyed Property");
4088 Property* property = expression_->AsProperty(); 4123 Property* property = expression_->AsProperty();
4089 ASSERT(property != NULL); 4124 ASSERT(property != NULL);
4090 __ RecordPosition(property->position()); 4125 __ RecordPosition(property->position());
4091 // Call IC code. 4126 // Call IC code.
4092 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 4127 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
4093 // TODO(1222589): Make the IC grab the values from the stack. 4128 // TODO(1222589): Make the IC grab the values from the stack.
4094 frame->Pop(eax); 4129 frame->EmitPop(eax);
4095 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4130 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4096 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4131 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4097 break; 4132 break;
4098 } 4133 }
4099 4134
4100 default: 4135 default:
4101 UNREACHABLE(); 4136 UNREACHABLE();
4102 } 4137 }
4103 } 4138 }
4104 4139
(...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after
5321 5356
5322 // Slow-case: Go through the JavaScript implementation. 5357 // Slow-case: Go through the JavaScript implementation.
5323 __ bind(&slow); 5358 __ bind(&slow);
5324 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5359 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5325 } 5360 }
5326 5361
5327 5362
5328 #undef __ 5363 #undef __
5329 5364
5330 } } // namespace v8::internal 5365 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/jump-target-ia32.cc » ('j') | src/virtual-frame-ia32.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698