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

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

Issue 11229: Experimental: change the name of the VirtualFrame function Push to... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | v8/src/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 } 125 }
126 #endif 126 #endif
127 127
128 // Allocate space for locals and initialize them. 128 // Allocate space for locals and initialize them.
129 frame_->AllocateStackSlots(scope_->num_stack_slots()); 129 frame_->AllocateStackSlots(scope_->num_stack_slots());
130 130
131 if (scope_->num_heap_slots() > 0) { 131 if (scope_->num_heap_slots() > 0) {
132 // Allocate local context. 132 // Allocate local context.
133 // Get outer context and create a new context based on it. 133 // Get outer context and create a new context based on it.
134 __ ldr(r0, frame_->Function()); 134 __ ldr(r0, frame_->Function());
135 frame_->Push(r0); 135 frame_->EmitPush(r0);
136 frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result 136 frame_->CallRuntime(Runtime::kNewContext, 1); // r0 holds the result
137 137
138 if (kDebug) { 138 if (kDebug) {
139 JumpTarget verified_true(this); 139 JumpTarget verified_true(this);
140 __ cmp(r0, Operand(cp)); 140 __ cmp(r0, Operand(cp));
141 verified_true.Branch(eq); 141 verified_true.Branch(eq);
142 __ stop("NewContext: r0 is expected to be the same as cp"); 142 __ stop("NewContext: r0 is expected to be the same as cp");
143 verified_true.Bind(); 143 verified_true.Bind();
144 } 144 }
145 // Update context local. 145 // Update context local.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 189 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
190 __ ldr(r2, frame_->Function()); 190 __ ldr(r2, frame_->Function());
191 // The receiver is below the arguments, the return address, 191 // The receiver is below the arguments, the return address,
192 // and the frame pointer on the stack. 192 // and the frame pointer on the stack.
193 const int kReceiverDisplacement = 2 + scope_->num_parameters(); 193 const int kReceiverDisplacement = 2 + scope_->num_parameters();
194 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); 194 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize));
195 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); 195 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
196 frame_->Adjust(3); 196 frame_->Adjust(3);
197 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); 197 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
198 frame_->CallStub(&stub, 3); 198 frame_->CallStub(&stub, 3);
199 frame_->Push(r0); 199 frame_->EmitPush(r0);
200 arguments_ref.SetValue(NOT_CONST_INIT); 200 arguments_ref.SetValue(NOT_CONST_INIT);
201 } 201 }
202 shadow_ref.SetValue(NOT_CONST_INIT); 202 shadow_ref.SetValue(NOT_CONST_INIT);
203 } 203 }
204 frame_->Drop(); // Value is no longer needed. 204 frame_->Drop(); // Value is no longer needed.
205 } 205 }
206 206
207 // Generate code to 'execute' declarations and initialize functions 207 // Generate code to 'execute' declarations and initialize functions
208 // (source elements). In case of an illegal redeclaration we need to 208 // (source elements). In case of an illegal redeclaration we need to
209 // handle that instead of processing the declarations. 209 // handle that instead of processing the declarations.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 // sp: stack pointer 249 // sp: stack pointer
250 // fp: frame pointer 250 // fp: frame pointer
251 // pp: parameter pointer 251 // pp: parameter pointer
252 // cp: callee's context 252 // cp: callee's context
253 __ mov(r0, Operand(Factory::undefined_value())); 253 __ mov(r0, Operand(Factory::undefined_value()));
254 254
255 function_return_.Bind(); 255 function_return_.Bind();
256 if (FLAG_trace) { 256 if (FLAG_trace) {
257 // Push the return value on the stack as the parameter. 257 // Push the return value on the stack as the parameter.
258 // Runtime::TraceExit returns the parameter as it is. 258 // Runtime::TraceExit returns the parameter as it is.
259 frame_->Push(r0); 259 frame_->EmitPush(r0);
260 frame_->CallRuntime(Runtime::kTraceExit, 1); 260 frame_->CallRuntime(Runtime::kTraceExit, 1);
261 } 261 }
262 262
263 // Tear down the frame which will restore the caller's frame pointer and 263 // Tear down the frame which will restore the caller's frame pointer and
264 // the link register. 264 // the link register.
265 frame_->Exit(); 265 frame_->Exit();
266 266
267 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); 267 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
268 __ mov(pc, lr); 268 __ mov(pc, lr);
269 } 269 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 JumpTarget true_target(this); 357 JumpTarget true_target(this);
358 JumpTarget false_target(this); 358 JumpTarget false_target(this);
359 LoadCondition(x, typeof_state, &true_target, &false_target, false); 359 LoadCondition(x, typeof_state, &true_target, &false_target, false);
360 360
361 if (has_cc()) { 361 if (has_cc()) {
362 // Convert cc_reg_ into a boolean value. 362 // Convert cc_reg_ into a boolean value.
363 JumpTarget loaded(this); 363 JumpTarget loaded(this);
364 JumpTarget materialize_true(this); 364 JumpTarget materialize_true(this);
365 materialize_true.Branch(cc_reg_); 365 materialize_true.Branch(cc_reg_);
366 __ mov(r0, Operand(Factory::false_value())); 366 __ mov(r0, Operand(Factory::false_value()));
367 frame_->Push(r0); 367 frame_->EmitPush(r0);
368 loaded.Jump(); 368 loaded.Jump();
369 materialize_true.Bind(); 369 materialize_true.Bind();
370 __ mov(r0, Operand(Factory::true_value())); 370 __ mov(r0, Operand(Factory::true_value()));
371 frame_->Push(r0); 371 frame_->EmitPush(r0);
372 loaded.Bind(); 372 loaded.Bind();
373 cc_reg_ = al; 373 cc_reg_ = al;
374 } 374 }
375 375
376 if (true_target.is_linked() || false_target.is_linked()) { 376 if (true_target.is_linked() || false_target.is_linked()) {
377 // We have at least one condition value that has been "translated" 377 // We have at least one condition value that has been "translated"
378 // into a branch, thus it needs to be loaded explicitly. 378 // into a branch, thus it needs to be loaded explicitly.
379 JumpTarget loaded(this); 379 JumpTarget loaded(this);
380 if (frame_ != NULL) { 380 if (frame_ != NULL) {
381 loaded.Jump(); // Don't lose the current TOS. 381 loaded.Jump(); // Don't lose the current TOS.
382 } 382 }
383 bool both = true_target.is_linked() && false_target.is_linked(); 383 bool both = true_target.is_linked() && false_target.is_linked();
384 // Load "true" if necessary. 384 // Load "true" if necessary.
385 if (true_target.is_linked()) { 385 if (true_target.is_linked()) {
386 true_target.Bind(); 386 true_target.Bind();
387 __ mov(r0, Operand(Factory::true_value())); 387 __ mov(r0, Operand(Factory::true_value()));
388 frame_->Push(r0); 388 frame_->EmitPush(r0);
389 } 389 }
390 // If both "true" and "false" need to be loaded jump across the code for 390 // If both "true" and "false" need to be loaded jump across the code for
391 // "false". 391 // "false".
392 if (both) { 392 if (both) {
393 loaded.Jump(); 393 loaded.Jump();
394 } 394 }
395 // Load "false" if necessary. 395 // Load "false" if necessary.
396 if (false_target.is_linked()) { 396 if (false_target.is_linked()) {
397 false_target.Bind(); 397 false_target.Bind();
398 __ mov(r0, Operand(Factory::false_value())); 398 __ mov(r0, Operand(Factory::false_value()));
399 frame_->Push(r0); 399 frame_->EmitPush(r0);
400 } 400 }
401 // A value is loaded on all paths reaching this point. 401 // A value is loaded on all paths reaching this point.
402 loaded.Bind(); 402 loaded.Bind();
403 } 403 }
404 ASSERT(frame_ != NULL); 404 ASSERT(frame_ != NULL);
405 ASSERT(!has_cc()); 405 ASSERT(!has_cc());
406 } 406 }
407 407
408 408
409 void CodeGenerator::LoadGlobal() { 409 void CodeGenerator::LoadGlobal() {
410 __ ldr(r0, GlobalObject()); 410 __ ldr(r0, GlobalObject());
411 frame_->Push(r0); 411 frame_->EmitPush(r0);
412 } 412 }
413 413
414 414
415 void CodeGenerator::LoadGlobalReceiver(Register scratch) { 415 void CodeGenerator::LoadGlobalReceiver(Register scratch) {
416 __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX)); 416 __ ldr(scratch, ContextOperand(cp, Context::GLOBAL_INDEX));
417 __ ldr(scratch, 417 __ ldr(scratch,
418 FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset)); 418 FieldMemOperand(scratch, GlobalObject::kGlobalReceiverOffset));
419 frame_->Push(scratch); 419 frame_->EmitPush(scratch);
420 } 420 }
421 421
422 422
423 // TODO(1241834): Get rid of this function in favor of just using Load, now 423 // TODO(1241834): Get rid of this function in favor of just using Load, now
424 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 424 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
425 // variables w/o reference errors elsewhere. 425 // variables w/o reference errors elsewhere.
426 void CodeGenerator::LoadTypeofExpression(Expression* x) { 426 void CodeGenerator::LoadTypeofExpression(Expression* x) {
427 Variable* variable = x->AsVariableProxy()->AsVariable(); 427 Variable* variable = x->AsVariableProxy()->AsVariable();
428 if (variable != NULL && !variable->is_this() && variable->is_global()) { 428 if (variable != NULL && !variable->is_this() && variable->is_global()) {
429 // NOTE: This is somewhat nasty. We force the compiler to load 429 // NOTE: This is somewhat nasty. We force the compiler to load
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 } 494 }
495 495
496 496
497 void CodeGenerator::UnloadReference(Reference* ref) { 497 void CodeGenerator::UnloadReference(Reference* ref) {
498 // Pop a reference from the stack while preserving TOS. 498 // Pop a reference from the stack while preserving TOS.
499 Comment cmnt(masm_, "[ UnloadReference"); 499 Comment cmnt(masm_, "[ UnloadReference");
500 int size = ref->size(); 500 int size = ref->size();
501 if (size > 0) { 501 if (size > 0) {
502 frame_->Pop(r0); 502 frame_->Pop(r0);
503 frame_->Drop(size); 503 frame_->Drop(size);
504 frame_->Push(r0); 504 frame_->EmitPush(r0);
505 } 505 }
506 } 506 }
507 507
508 508
509 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given 509 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
510 // register to a boolean in the condition code register. The code 510 // register to a boolean in the condition code register. The code
511 // may jump to 'false_target' in case the register converts to 'false'. 511 // may jump to 'false_target' in case the register converts to 'false'.
512 void CodeGenerator::ToBoolean(JumpTarget* true_target, 512 void CodeGenerator::ToBoolean(JumpTarget* true_target,
513 JumpTarget* false_target) { 513 JumpTarget* false_target) {
514 // Note: The generated code snippet does not change stack variables. 514 // Note: The generated code snippet does not change stack variables.
(...skipping 14 matching lines...) Expand all
529 __ cmp(r0, Operand(Factory::undefined_value())); 529 __ cmp(r0, Operand(Factory::undefined_value()));
530 false_target->Branch(eq); 530 false_target->Branch(eq);
531 531
532 // Check if the value is a smi. 532 // Check if the value is a smi.
533 __ cmp(r0, Operand(Smi::FromInt(0))); 533 __ cmp(r0, Operand(Smi::FromInt(0)));
534 false_target->Branch(eq); 534 false_target->Branch(eq);
535 __ tst(r0, Operand(kSmiTagMask)); 535 __ tst(r0, Operand(kSmiTagMask));
536 true_target->Branch(eq); 536 true_target->Branch(eq);
537 537
538 // Slow case: call the runtime. 538 // Slow case: call the runtime.
539 frame_->Push(r0); 539 frame_->EmitPush(r0);
540 frame_->CallRuntime(Runtime::kToBool, 1); 540 frame_->CallRuntime(Runtime::kToBool, 1);
541 // Convert the result (r0) to a condition code. 541 // Convert the result (r0) to a condition code.
542 __ cmp(r0, Operand(Factory::false_value())); 542 __ cmp(r0, Operand(Factory::false_value()));
543 543
544 cc_reg_ = ne; 544 cc_reg_ = ne;
545 } 545 }
546 546
547 547
548 class GetPropertyStub : public CodeStub { 548 class GetPropertyStub : public CodeStub {
549 public: 549 public:
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 } 809 }
810 __ bind(deferred->exit()); 810 __ bind(deferred->exit());
811 break; 811 break;
812 } 812 }
813 813
814 case Token::SHL: 814 case Token::SHL:
815 case Token::SHR: 815 case Token::SHR:
816 case Token::SAR: { 816 case Token::SAR: {
817 if (reversed) { 817 if (reversed) {
818 __ mov(ip, Operand(value)); 818 __ mov(ip, Operand(value));
819 frame_->Push(ip); 819 frame_->EmitPush(ip);
820 frame_->Push(r0); 820 frame_->EmitPush(r0);
821 GenericBinaryOperation(op); 821 GenericBinaryOperation(op);
822 822
823 } else { 823 } else {
824 int shift_value = int_value & 0x1f; // least significant 5 bits 824 int shift_value = int_value & 0x1f; // least significant 5 bits
825 DeferredCode* deferred = 825 DeferredCode* deferred =
826 new DeferredInlinedSmiOperation(this, op, shift_value, false); 826 new DeferredInlinedSmiOperation(this, op, shift_value, false);
827 __ tst(r0, Operand(kSmiTagMask)); 827 __ tst(r0, Operand(kSmiTagMask));
828 __ b(ne, deferred->enter()); 828 __ b(ne, deferred->enter());
829 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags 829 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags
830 switch (op) { 830 switch (op) {
(...skipping 29 matching lines...) Expand all
860 default: UNREACHABLE(); 860 default: UNREACHABLE();
861 } 861 }
862 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); 862 __ mov(r0, Operand(r2, LSL, kSmiTagSize));
863 __ bind(deferred->exit()); 863 __ bind(deferred->exit());
864 } 864 }
865 break; 865 break;
866 } 866 }
867 867
868 default: 868 default:
869 if (!reversed) { 869 if (!reversed) {
870 frame_->Push(r0); 870 frame_->EmitPush(r0);
871 __ mov(r0, Operand(value)); 871 __ mov(r0, Operand(value));
872 frame_->Push(r0); 872 frame_->EmitPush(r0);
873 } else { 873 } else {
874 __ mov(ip, Operand(value)); 874 __ mov(ip, Operand(value));
875 frame_->Push(ip); 875 frame_->EmitPush(ip);
876 frame_->Push(r0); 876 frame_->EmitPush(r0);
877 } 877 }
878 GenericBinaryOperation(op); 878 GenericBinaryOperation(op);
879 break; 879 break;
880 } 880 }
881 881
882 exit.Bind(); 882 exit.Bind();
883 } 883 }
884 884
885 885
886 void CodeGenerator::Comparison(Condition cc, bool strict) { 886 void CodeGenerator::Comparison(Condition cc, bool strict) {
(...skipping 13 matching lines...) Expand all
900 frame_->Pop(r0); 900 frame_->Pop(r0);
901 } else { 901 } else {
902 frame_->Pop(r0); 902 frame_->Pop(r0);
903 frame_->Pop(r1); 903 frame_->Pop(r1);
904 } 904 }
905 __ orr(r2, r0, Operand(r1)); 905 __ orr(r2, r0, Operand(r1));
906 __ tst(r2, Operand(kSmiTagMask)); 906 __ tst(r2, Operand(kSmiTagMask));
907 smi.Branch(eq); 907 smi.Branch(eq);
908 908
909 // Perform non-smi comparison by runtime call. 909 // Perform non-smi comparison by runtime call.
910 frame_->Push(r1); 910 frame_->EmitPush(r1);
911 911
912 // Figure out which native to call and setup the arguments. 912 // Figure out which native to call and setup the arguments.
913 Builtins::JavaScript native; 913 Builtins::JavaScript native;
914 int arg_count = 1; 914 int arg_count = 1;
915 if (cc == eq) { 915 if (cc == eq) {
916 native = strict ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 916 native = strict ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
917 } else { 917 } else {
918 native = Builtins::COMPARE; 918 native = Builtins::COMPARE;
919 int ncr; // NaN compare result 919 int ncr; // NaN compare result
920 if (cc == lt || cc == le) { 920 if (cc == lt || cc == le) {
921 ncr = GREATER; 921 ncr = GREATER;
922 } else { 922 } else {
923 ASSERT(cc == gt || cc == ge); // remaining cases 923 ASSERT(cc == gt || cc == ge); // remaining cases
924 ncr = LESS; 924 ncr = LESS;
925 } 925 }
926 frame_->Push(r0); 926 frame_->EmitPush(r0);
927 arg_count++; 927 arg_count++;
928 __ mov(r0, Operand(Smi::FromInt(ncr))); 928 __ mov(r0, Operand(Smi::FromInt(ncr)));
929 } 929 }
930 930
931 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 931 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
932 // tagged as a small integer. 932 // tagged as a small integer.
933 frame_->Push(r0); 933 frame_->EmitPush(r0);
934 __ mov(r0, Operand(arg_count)); 934 __ mov(r0, Operand(arg_count));
935 frame_->InvokeBuiltin(native, CALL_JS, arg_count + 1); 935 frame_->InvokeBuiltin(native, CALL_JS, arg_count + 1);
936 __ cmp(r0, Operand(0)); 936 __ cmp(r0, Operand(0));
937 exit.Jump(); 937 exit.Jump();
938 938
939 // test smi equality by pointer comparison. 939 // test smi equality by pointer comparison.
940 smi.Bind(); 940 smi.Bind();
941 __ cmp(r1, Operand(r0)); 941 __ cmp(r1, Operand(r0));
942 942
943 exit.Bind(); 943 exit.Bind();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 node->break_target()->set_code_generator(this); 1016 node->break_target()->set_code_generator(this);
1017 VisitStatements(node->statements()); 1017 VisitStatements(node->statements());
1018 if (node->break_target()->is_linked()) { 1018 if (node->break_target()->is_linked()) {
1019 node->break_target()->Bind(); 1019 node->break_target()->Bind();
1020 } 1020 }
1021 } 1021 }
1022 1022
1023 1023
1024 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1024 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1025 __ mov(r0, Operand(pairs)); 1025 __ mov(r0, Operand(pairs));
1026 frame_->Push(r0); 1026 frame_->EmitPush(r0);
1027 frame_->Push(cp); 1027 frame_->EmitPush(cp);
1028 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 1028 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
1029 frame_->Push(r0); 1029 frame_->EmitPush(r0);
1030 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1030 frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1031 // The result is discarded. 1031 // The result is discarded.
1032 } 1032 }
1033 1033
1034 1034
1035 void CodeGenerator::VisitDeclaration(Declaration* node) { 1035 void CodeGenerator::VisitDeclaration(Declaration* node) {
1036 Comment cmnt(masm_, "[ Declaration"); 1036 Comment cmnt(masm_, "[ Declaration");
1037 Variable* var = node->proxy()->var(); 1037 Variable* var = node->proxy()->var();
1038 ASSERT(var != NULL); // must have been resolved 1038 ASSERT(var != NULL); // must have been resolved
1039 Slot* slot = var->slot(); 1039 Slot* slot = var->slot();
1040 1040
1041 // If it was not possible to allocate the variable at compile time, 1041 // If it was not possible to allocate the variable at compile time,
1042 // we need to "declare" it at runtime to make sure it actually 1042 // we need to "declare" it at runtime to make sure it actually
1043 // exists in the local context. 1043 // exists in the local context.
1044 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1044 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1045 // Variables with a "LOOKUP" slot were introduced as non-locals 1045 // Variables with a "LOOKUP" slot were introduced as non-locals
1046 // during variable resolution and must have mode DYNAMIC. 1046 // during variable resolution and must have mode DYNAMIC.
1047 ASSERT(var->mode() == Variable::DYNAMIC); 1047 ASSERT(var->mode() == Variable::DYNAMIC);
1048 // For now, just do a runtime call. 1048 // For now, just do a runtime call.
1049 frame_->Push(cp); 1049 frame_->EmitPush(cp);
1050 __ mov(r0, Operand(var->name())); 1050 __ mov(r0, Operand(var->name()));
1051 frame_->Push(r0); 1051 frame_->EmitPush(r0);
1052 // Declaration nodes are always declared in only two modes. 1052 // Declaration nodes are always declared in only two modes.
1053 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 1053 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
1054 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1054 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1055 __ mov(r0, Operand(Smi::FromInt(attr))); 1055 __ mov(r0, Operand(Smi::FromInt(attr)));
1056 frame_->Push(r0); 1056 frame_->EmitPush(r0);
1057 // Push initial value, if any. 1057 // Push initial value, if any.
1058 // Note: For variables we must not push an initial value (such as 1058 // Note: For variables we must not push an initial value (such as
1059 // 'undefined') because we may have a (legal) redeclaration and we 1059 // 'undefined') because we may have a (legal) redeclaration and we
1060 // must not destroy the current value. 1060 // must not destroy the current value.
1061 if (node->mode() == Variable::CONST) { 1061 if (node->mode() == Variable::CONST) {
1062 __ mov(r0, Operand(Factory::the_hole_value())); 1062 __ mov(r0, Operand(Factory::the_hole_value()));
1063 frame_->Push(r0); 1063 frame_->EmitPush(r0);
1064 } else if (node->fun() != NULL) { 1064 } else if (node->fun() != NULL) {
1065 Load(node->fun()); 1065 Load(node->fun());
1066 } else { 1066 } else {
1067 __ mov(r0, Operand(0)); // no initial value! 1067 __ mov(r0, Operand(0)); // no initial value!
1068 frame_->Push(r0); 1068 frame_->EmitPush(r0);
1069 } 1069 }
1070 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); 1070 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
1071 // Ignore the return value (declarations are statements). 1071 // Ignore the return value (declarations are statements).
1072 return; 1072 return;
1073 } 1073 }
1074 1074
1075 ASSERT(!var->is_global()); 1075 ASSERT(!var->is_global());
1076 1076
1077 // If we have a function or a constant, we need to initialize the variable. 1077 // If we have a function or a constant, we need to initialize the variable.
1078 Expression* val = NULL; 1078 Expression* val = NULL;
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 frame_->Pop(r0); 1278 frame_->Pop(r0);
1279 1279
1280 // Test for a Smi value in a HeapNumber. 1280 // Test for a Smi value in a HeapNumber.
1281 JumpTarget is_smi(this); 1281 JumpTarget is_smi(this);
1282 __ tst(r0, Operand(kSmiTagMask)); 1282 __ tst(r0, Operand(kSmiTagMask));
1283 is_smi.Branch(eq); 1283 is_smi.Branch(eq);
1284 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag)); 1284 __ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
1285 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag)); 1285 __ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
1286 __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); 1286 __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
1287 fail_label->Branch(ne); 1287 fail_label->Branch(ne);
1288 frame_->Push(r0); 1288 frame_->EmitPush(r0);
1289 frame_->CallRuntime(Runtime::kNumberToSmi, 1); 1289 frame_->CallRuntime(Runtime::kNumberToSmi, 1);
1290 is_smi.Bind(); 1290 is_smi.Bind();
1291 1291
1292 if (min_index != 0) { 1292 if (min_index != 0) {
1293 // Small positive numbers can be immediate operands. 1293 // Small positive numbers can be immediate operands.
1294 if (min_index < 0) { 1294 if (min_index < 0) {
1295 // If min_index is Smi::kMinValue, -min_index is not a Smi. 1295 // If min_index is Smi::kMinValue, -min_index is not a Smi.
1296 if (Smi::IsValid(-min_index)) { 1296 if (Smi::IsValid(-min_index)) {
1297 __ add(r0, r0, Operand(Smi::FromInt(-min_index))); 1297 __ add(r0, r0, Operand(Smi::FromInt(-min_index)));
1298 } else { 1298 } else {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 default_clause = clause; 1351 default_clause = clause;
1352 continue; 1352 continue;
1353 } 1353 }
1354 1354
1355 Comment cmnt(masm_, "[ Case clause"); 1355 Comment cmnt(masm_, "[ Case clause");
1356 // Compile the test. 1356 // Compile the test.
1357 next_test.Bind(); 1357 next_test.Bind();
1358 next_test.Unuse(); 1358 next_test.Unuse();
1359 // Duplicate TOS. 1359 // Duplicate TOS.
1360 __ ldr(r0, frame_->Top()); 1360 __ ldr(r0, frame_->Top());
1361 frame_->Push(r0); 1361 frame_->EmitPush(r0);
1362 Load(clause->label()); 1362 Load(clause->label());
1363 Comparison(eq, true); 1363 Comparison(eq, true);
1364 Branch(false, &next_test); 1364 Branch(false, &next_test);
1365 1365
1366 // Before entering the body from the test, remove the switch value from 1366 // Before entering the body from the test, remove the switch value from
1367 // the stack. 1367 // the stack.
1368 frame_->Drop(); 1368 frame_->Drop();
1369 1369
1370 // Label the body so that fall through is enabled. 1370 // Label the body so that fall through is enabled.
1371 if (i > 0 && cases->at(i - 1)->is_default()) { 1371 if (i > 0 && cases->at(i - 1)->is_default()) {
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 1628
1629 // Check if enumerable is already a JSObject 1629 // Check if enumerable is already a JSObject
1630 __ tst(r0, Operand(kSmiTagMask)); 1630 __ tst(r0, Operand(kSmiTagMask));
1631 primitive.Branch(eq); 1631 primitive.Branch(eq);
1632 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1632 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
1633 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 1633 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
1634 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 1634 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
1635 jsobject.Branch(hs); 1635 jsobject.Branch(hs);
1636 1636
1637 primitive.Bind(); 1637 primitive.Bind();
1638 frame_->Push(r0); 1638 frame_->EmitPush(r0);
1639 __ mov(r0, Operand(0)); 1639 __ mov(r0, Operand(0));
1640 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, 1); 1640 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, 1);
1641 1641
1642 1642
1643 jsobject.Bind(); 1643 jsobject.Bind();
1644 1644
1645 // Get the set of properties (as a FixedArray or Map). 1645 // Get the set of properties (as a FixedArray or Map).
1646 frame_->Push(r0); // duplicate the object being enumerated 1646 frame_->EmitPush(r0); // duplicate the object being enumerated
1647 frame_->Push(r0); 1647 frame_->EmitPush(r0);
1648 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1648 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1649 1649
1650 // If we got a Map, we can do a fast modification check. 1650 // If we got a Map, we can do a fast modification check.
1651 // Otherwise, we got a FixedArray, and we have to do a slow check. 1651 // Otherwise, we got a FixedArray, and we have to do a slow check.
1652 __ mov(r2, Operand(r0)); 1652 __ mov(r2, Operand(r0));
1653 __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset)); 1653 __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));
1654 __ cmp(r1, Operand(Factory::meta_map())); 1654 __ cmp(r1, Operand(Factory::meta_map()));
1655 fixed_array.Branch(ne); 1655 fixed_array.Branch(ne);
1656 1656
1657 // Get enum cache 1657 // Get enum cache
1658 __ mov(r1, Operand(r0)); 1658 __ mov(r1, Operand(r0));
1659 __ ldr(r1, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset)); 1659 __ ldr(r1, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset));
1660 __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); 1660 __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
1661 __ ldr(r2, 1661 __ ldr(r2,
1662 FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1662 FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
1663 1663
1664 frame_->Push(r0); // map 1664 frame_->EmitPush(r0); // map
1665 frame_->Push(r2); // enum cache bridge cache 1665 frame_->EmitPush(r2); // enum cache bridge cache
1666 __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset)); 1666 __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset));
1667 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1667 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1668 frame_->Push(r0); 1668 frame_->EmitPush(r0);
1669 __ mov(r0, Operand(Smi::FromInt(0))); 1669 __ mov(r0, Operand(Smi::FromInt(0)));
1670 frame_->Push(r0); 1670 frame_->EmitPush(r0);
1671 entry.Jump(); 1671 entry.Jump();
1672 1672
1673 1673
1674 fixed_array.Bind(); 1674 fixed_array.Bind();
1675 1675
1676 __ mov(r1, Operand(Smi::FromInt(0))); 1676 __ mov(r1, Operand(Smi::FromInt(0)));
1677 frame_->Push(r1); // insert 0 in place of Map 1677 frame_->EmitPush(r1); // insert 0 in place of Map
1678 frame_->Push(r0); 1678 frame_->EmitPush(r0);
1679 1679
1680 // Push the length of the array and the initial index onto the stack. 1680 // Push the length of the array and the initial index onto the stack.
1681 __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset)); 1681 __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset));
1682 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1682 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
1683 frame_->Push(r0); 1683 frame_->EmitPush(r0);
1684 __ mov(r0, Operand(Smi::FromInt(0))); // init index 1684 __ mov(r0, Operand(Smi::FromInt(0))); // init index
1685 frame_->Push(r0); 1685 frame_->EmitPush(r0);
1686 1686
1687 // Condition. 1687 // Condition.
1688 entry.Bind(); 1688 entry.Bind();
1689 1689
1690 // sp[0] : index 1690 // sp[0] : index
1691 // sp[1] : array/enum cache length 1691 // sp[1] : array/enum cache length
1692 // sp[2] : array or enum cache 1692 // sp[2] : array or enum cache
1693 // sp[3] : 0 or map 1693 // sp[3] : 0 or map
1694 // sp[4] : enumerable 1694 // sp[4] : enumerable
1695 __ ldr(r0, frame_->ElementAt(0)); // load the current count 1695 __ ldr(r0, frame_->ElementAt(0)); // load the current count
(...skipping 12 matching lines...) Expand all
1708 __ ldr(r2, frame_->ElementAt(3)); 1708 __ ldr(r2, frame_->ElementAt(3));
1709 // Check if this (still) matches the map of the enumerable. 1709 // Check if this (still) matches the map of the enumerable.
1710 // If not, we have to filter the key. 1710 // If not, we have to filter the key.
1711 __ ldr(r1, frame_->ElementAt(4)); 1711 __ ldr(r1, frame_->ElementAt(4));
1712 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 1712 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
1713 __ cmp(r1, Operand(r2)); 1713 __ cmp(r1, Operand(r2));
1714 end_del_check.Branch(eq); 1714 end_del_check.Branch(eq);
1715 1715
1716 // Convert the entry to a string (or null if it isn't a property anymore). 1716 // Convert the entry to a string (or null if it isn't a property anymore).
1717 __ ldr(r0, frame_->ElementAt(4)); // push enumerable 1717 __ ldr(r0, frame_->ElementAt(4)); // push enumerable
1718 frame_->Push(r0); 1718 frame_->EmitPush(r0);
1719 frame_->Push(r3); // push entry 1719 frame_->EmitPush(r3); // push entry
1720 __ mov(r0, Operand(1)); 1720 __ mov(r0, Operand(1));
1721 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, 2); 1721 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, 2);
1722 __ mov(r3, Operand(r0)); 1722 __ mov(r3, Operand(r0));
1723 1723
1724 // If the property has been removed while iterating, we just skip it. 1724 // If the property has been removed while iterating, we just skip it.
1725 __ cmp(r3, Operand(Factory::null_value())); 1725 __ cmp(r3, Operand(Factory::null_value()));
1726 node->continue_target()->Branch(eq); 1726 node->continue_target()->Branch(eq);
1727 1727
1728 end_del_check.Bind(); 1728 end_del_check.Bind();
1729 // Store the entry in the 'each' expression and take another spin in the 1729 // Store the entry in the 'each' expression and take another spin in the
1730 // loop. r3: i'th entry of the enum cache (or string there of) 1730 // loop. r3: i'th entry of the enum cache (or string there of)
1731 frame_->Push(r3); // push entry 1731 frame_->EmitPush(r3); // push entry
1732 { Reference each(this, node->each()); 1732 { Reference each(this, node->each());
1733 if (!each.is_illegal()) { 1733 if (!each.is_illegal()) {
1734 if (each.size() > 0) { 1734 if (each.size() > 0) {
1735 __ ldr(r0, frame_->ElementAt(each.size())); 1735 __ ldr(r0, frame_->ElementAt(each.size()));
1736 frame_->Push(r0); 1736 frame_->EmitPush(r0);
1737 } 1737 }
1738 // If the reference was to a slot we rely on the convenient property 1738 // If the reference was to a slot we rely on the convenient property
1739 // that it doesn't matter whether a value (eg, r3 pushed above) is 1739 // that it doesn't matter whether a value (eg, r3 pushed above) is
1740 // right on top of or right underneath a zero-sized reference. 1740 // right on top of or right underneath a zero-sized reference.
1741 each.SetValue(NOT_CONST_INIT); 1741 each.SetValue(NOT_CONST_INIT);
1742 if (each.size() > 0) { 1742 if (each.size() > 0) {
1743 // It's safe to pop the value lying on top of the reference before 1743 // It's safe to pop the value lying on top of the reference before
1744 // unloading the reference itself (which preserves the top of stack, 1744 // unloading the reference itself (which preserves the top of stack,
1745 // ie, now the topmost value of the non-zero sized reference), since 1745 // ie, now the topmost value of the non-zero sized reference), since
1746 // we will discard the top of stack after unloading the reference 1746 // we will discard the top of stack after unloading the reference
1747 // anyway. 1747 // anyway.
1748 frame_->Pop(r0); 1748 frame_->Pop(r0);
1749 } 1749 }
1750 } 1750 }
1751 } 1751 }
1752 // Discard the i'th entry pushed above or else the remainder of the 1752 // Discard the i'th entry pushed above or else the remainder of the
1753 // reference, whichever is currently on top of the stack. 1753 // reference, whichever is currently on top of the stack.
1754 frame_->Drop(); 1754 frame_->Drop();
1755 1755
1756 // Body. 1756 // Body.
1757 CheckStack(); // TODO(1222600): ignore if body contains calls. 1757 CheckStack(); // TODO(1222600): ignore if body contains calls.
1758 Visit(node->body()); 1758 Visit(node->body());
1759 1759
1760 // Next. 1760 // Next.
1761 node->continue_target()->Bind(); 1761 node->continue_target()->Bind();
1762 frame_->Pop(r0); 1762 frame_->Pop(r0);
1763 __ add(r0, r0, Operand(Smi::FromInt(1))); 1763 __ add(r0, r0, Operand(Smi::FromInt(1)));
1764 frame_->Push(r0); 1764 frame_->EmitPush(r0);
1765 entry.Jump(); 1765 entry.Jump();
1766 1766
1767 // Cleanup. 1767 // Cleanup.
1768 cleanup.Bind(); 1768 cleanup.Bind();
1769 node->break_target()->Bind(); 1769 node->break_target()->Bind();
1770 frame_->Drop(5); 1770 frame_->Drop(5);
1771 1771
1772 // Exit. 1772 // Exit.
1773 exit.Bind(); 1773 exit.Bind();
1774 1774
1775 break_stack_height_ -= kForInStackSize; 1775 break_stack_height_ -= kForInStackSize;
1776 } 1776 }
1777 1777
1778 1778
1779 void CodeGenerator::VisitTryCatch(TryCatch* node) { 1779 void CodeGenerator::VisitTryCatch(TryCatch* node) {
1780 Comment cmnt(masm_, "[ TryCatch"); 1780 Comment cmnt(masm_, "[ TryCatch");
1781 1781
1782 JumpTarget try_block(this); 1782 JumpTarget try_block(this);
1783 JumpTarget exit(this); 1783 JumpTarget exit(this);
1784 1784
1785 try_block.Call(); 1785 try_block.Call();
1786 // --- Catch block --- 1786 // --- Catch block ---
1787 frame_->Push(r0); 1787 frame_->EmitPush(r0);
1788 1788
1789 // Store the caught exception in the catch variable. 1789 // Store the caught exception in the catch variable.
1790 { Reference ref(this, node->catch_var()); 1790 { Reference ref(this, node->catch_var());
1791 ASSERT(ref.is_slot()); 1791 ASSERT(ref.is_slot());
1792 // Here we make use of the convenient property that it doesn't matter 1792 // Here we make use of the convenient property that it doesn't matter
1793 // whether a value is immediately on top of or underneath a zero-sized 1793 // whether a value is immediately on top of or underneath a zero-sized
1794 // reference. 1794 // reference.
1795 ref.SetValue(NOT_CONST_INIT); 1795 ref.SetValue(NOT_CONST_INIT);
1796 } 1796 }
1797 1797
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1892 // block. Should probably be extended to hold information for 1892 // block. Should probably be extended to hold information for
1893 // break/continue from within the try block. 1893 // break/continue from within the try block.
1894 enum { FALLING, THROWING, JUMPING }; 1894 enum { FALLING, THROWING, JUMPING };
1895 1895
1896 JumpTarget unlink(this); 1896 JumpTarget unlink(this);
1897 JumpTarget try_block(this); 1897 JumpTarget try_block(this);
1898 JumpTarget finally_block(this); 1898 JumpTarget finally_block(this);
1899 1899
1900 try_block.Call(); 1900 try_block.Call();
1901 1901
1902 frame_->Push(r0); // save exception object on the stack 1902 frame_->EmitPush(r0); // save exception object on the stack
1903 // In case of thrown exceptions, this is where we continue. 1903 // In case of thrown exceptions, this is where we continue.
1904 __ mov(r2, Operand(Smi::FromInt(THROWING))); 1904 __ mov(r2, Operand(Smi::FromInt(THROWING)));
1905 finally_block.Jump(); 1905 finally_block.Jump();
1906 1906
1907 1907
1908 // --- Try block --- 1908 // --- Try block ---
1909 try_block.Bind(); 1909 try_block.Bind();
1910 1910
1911 frame_->PushTryHandler(TRY_FINALLY_HANDLER); 1911 frame_->PushTryHandler(TRY_FINALLY_HANDLER);
1912 int handler_height = frame_->height(); 1912 int handler_height = frame_->height();
(...skipping 23 matching lines...) Expand all
1936 for (int i = 0; i <= nof_escapes; i++) { 1936 for (int i = 0; i <= nof_escapes; i++) {
1937 shadows[i]->StopShadowing(); 1937 shadows[i]->StopShadowing();
1938 if (shadows[i]->is_linked()) nof_unlinks++; 1938 if (shadows[i]->is_linked()) nof_unlinks++;
1939 } 1939 }
1940 function_return_is_shadowed_ = function_return_was_shadowed; 1940 function_return_is_shadowed_ = function_return_was_shadowed;
1941 1941
1942 // If we can fall off the end of the try block, set the state on the stack 1942 // If we can fall off the end of the try block, set the state on the stack
1943 // to FALLING. 1943 // to FALLING.
1944 if (frame_ != NULL) { 1944 if (frame_ != NULL) {
1945 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS 1945 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS
1946 frame_->Push(r0); 1946 frame_->EmitPush(r0);
1947 __ mov(r2, Operand(Smi::FromInt(FALLING))); 1947 __ mov(r2, Operand(Smi::FromInt(FALLING)));
1948 if (nof_unlinks > 0) { 1948 if (nof_unlinks > 0) {
1949 unlink.Jump(); 1949 unlink.Jump();
1950 } 1950 }
1951 } 1951 }
1952 1952
1953 // Generate code to set the state for the (formerly) shadowing labels that 1953 // Generate code to set the state for the (formerly) shadowing labels that
1954 // have been jumped to. 1954 // have been jumped to.
1955 for (int i = 0; i <= nof_escapes; i++) { 1955 for (int i = 0; i <= nof_escapes; i++) {
1956 if (shadows[i]->is_linked()) { 1956 if (shadows[i]->is_linked()) {
1957 shadows[i]->Bind(); 1957 shadows[i]->Bind();
1958 if (shadows[i]->original_target() == &function_return_) { 1958 if (shadows[i]->original_target() == &function_return_) {
1959 // If this label shadowed the function return, materialize the 1959 // If this label shadowed the function return, materialize the
1960 // return value on the stack. 1960 // return value on the stack.
1961 frame_->Push(r0); 1961 frame_->EmitPush(r0);
1962 } else { 1962 } else {
1963 // Fake TOS for labels that shadowed breaks and continues. 1963 // Fake TOS for labels that shadowed breaks and continues.
1964 __ mov(r0, Operand(Factory::undefined_value())); 1964 __ mov(r0, Operand(Factory::undefined_value()));
1965 frame_->Push(r0); 1965 frame_->EmitPush(r0);
1966 } 1966 }
1967 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); 1967 __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
1968 unlink.Jump(); 1968 unlink.Jump();
1969 } 1969 }
1970 } 1970 }
1971 1971
1972 // Unlink from try chain; 1972 // Unlink from try chain;
1973 unlink.Bind(); 1973 unlink.Bind();
1974 1974
1975 frame_->Pop(r0); // Store TOS in r0 across stack manipulation 1975 frame_->Pop(r0); // Store TOS in r0 across stack manipulation
1976 // Reload sp from the top handler, because some statements that we 1976 // Reload sp from the top handler, because some statements that we
1977 // break from (eg, for...in) may have left stuff on the stack. 1977 // break from (eg, for...in) may have left stuff on the stack.
1978 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 1978 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
1979 __ ldr(sp, MemOperand(r3)); 1979 __ ldr(sp, MemOperand(r3));
1980 frame_->Forget(frame_->height() - handler_height); 1980 frame_->Forget(frame_->height() - handler_height);
1981 const int kNextIndex = (StackHandlerConstants::kNextOffset 1981 const int kNextIndex = (StackHandlerConstants::kNextOffset
1982 + StackHandlerConstants::kAddressDisplacement) 1982 + StackHandlerConstants::kAddressDisplacement)
1983 / kPointerSize; 1983 / kPointerSize;
1984 __ ldr(r1, frame_->ElementAt(kNextIndex)); 1984 __ ldr(r1, frame_->ElementAt(kNextIndex));
1985 __ str(r1, MemOperand(r3)); 1985 __ str(r1, MemOperand(r3));
1986 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 1986 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
1987 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 1987 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
1988 // Code slot popped. 1988 // Code slot popped.
1989 frame_->Forget(1); 1989 frame_->Forget(1);
1990 frame_->Push(r0); 1990 frame_->EmitPush(r0);
1991 1991
1992 // --- Finally block --- 1992 // --- Finally block ---
1993 finally_block.Bind(); 1993 finally_block.Bind();
1994 1994
1995 // Push the state on the stack. 1995 // Push the state on the stack.
1996 frame_->Push(r2); 1996 frame_->EmitPush(r2);
1997 1997
1998 // We keep two elements on the stack - the (possibly faked) result 1998 // We keep two elements on the stack - the (possibly faked) result
1999 // and the state - while evaluating the finally block. Record it, so 1999 // and the state - while evaluating the finally block. Record it, so
2000 // that a break/continue crossing this statement can restore the 2000 // that a break/continue crossing this statement can restore the
2001 // stack. 2001 // stack.
2002 const int kFinallyStackSize = 2 * kPointerSize; 2002 const int kFinallyStackSize = 2 * kPointerSize;
2003 break_stack_height_ += kFinallyStackSize; 2003 break_stack_height_ += kFinallyStackSize;
2004 2004
2005 // Generate code for the statements in the finally block. 2005 // Generate code for the statements in the finally block.
2006 VisitStatements(node->finally_block()->statements()); 2006 VisitStatements(node->finally_block()->statements());
(...skipping 19 matching lines...) Expand all
2026 shadows[i]->original_target()->Branch(eq); 2026 shadows[i]->original_target()->Branch(eq);
2027 } 2027 }
2028 } 2028 }
2029 } 2029 }
2030 2030
2031 // Check if we need to rethrow the exception. 2031 // Check if we need to rethrow the exception.
2032 __ cmp(r2, Operand(Smi::FromInt(THROWING))); 2032 __ cmp(r2, Operand(Smi::FromInt(THROWING)));
2033 exit.Branch(ne); 2033 exit.Branch(ne);
2034 2034
2035 // Rethrow exception. 2035 // Rethrow exception.
2036 frame_->Push(r0); 2036 frame_->EmitPush(r0);
2037 frame_->CallRuntime(Runtime::kReThrow, 1); 2037 frame_->CallRuntime(Runtime::kReThrow, 1);
2038 2038
2039 // Done. 2039 // Done.
2040 exit.Bind(); 2040 exit.Bind();
2041 } 2041 }
2042 } 2042 }
2043 2043
2044 2044
2045 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2045 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2046 Comment cmnt(masm_, "[ DebuggerStatament"); 2046 Comment cmnt(masm_, "[ DebuggerStatament");
2047 if (FLAG_debug_info) RecordStatementPosition(node); 2047 if (FLAG_debug_info) RecordStatementPosition(node);
2048 frame_->CallRuntime(Runtime::kDebugBreak, 0); 2048 frame_->CallRuntime(Runtime::kDebugBreak, 0);
2049 // Ignore the return value. 2049 // Ignore the return value.
2050 } 2050 }
2051 2051
2052 2052
2053 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 2053 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
2054 ASSERT(boilerplate->IsBoilerplate()); 2054 ASSERT(boilerplate->IsBoilerplate());
2055 2055
2056 // Push the boilerplate on the stack. 2056 // Push the boilerplate on the stack.
2057 __ mov(r0, Operand(boilerplate)); 2057 __ mov(r0, Operand(boilerplate));
2058 frame_->Push(r0); 2058 frame_->EmitPush(r0);
2059 2059
2060 // Create a new closure. 2060 // Create a new closure.
2061 frame_->Push(cp); 2061 frame_->EmitPush(cp);
2062 frame_->CallRuntime(Runtime::kNewClosure, 2); 2062 frame_->CallRuntime(Runtime::kNewClosure, 2);
2063 frame_->Push(r0); 2063 frame_->EmitPush(r0);
2064 } 2064 }
2065 2065
2066 2066
2067 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2067 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2068 Comment cmnt(masm_, "[ FunctionLiteral"); 2068 Comment cmnt(masm_, "[ FunctionLiteral");
2069 2069
2070 // Build the function boilerplate and instantiate it. 2070 // Build the function boilerplate and instantiate it.
2071 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 2071 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
2072 // Check for stack-overflow exception. 2072 // Check for stack-overflow exception.
2073 if (HasStackOverflow()) return; 2073 if (HasStackOverflow()) return;
(...skipping 22 matching lines...) Expand all
2096 Load(node->else_expression(), typeof_state()); 2096 Load(node->else_expression(), typeof_state());
2097 exit.Bind(); 2097 exit.Bind();
2098 } 2098 }
2099 2099
2100 2100
2101 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2101 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2102 if (slot->type() == Slot::LOOKUP) { 2102 if (slot->type() == Slot::LOOKUP) {
2103 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2103 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2104 2104
2105 // For now, just do a runtime call. 2105 // For now, just do a runtime call.
2106 frame_->Push(cp); 2106 frame_->EmitPush(cp);
2107 __ mov(r0, Operand(slot->var()->name())); 2107 __ mov(r0, Operand(slot->var()->name()));
2108 frame_->Push(r0); 2108 frame_->EmitPush(r0);
2109 2109
2110 if (typeof_state == INSIDE_TYPEOF) { 2110 if (typeof_state == INSIDE_TYPEOF) {
2111 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2111 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2112 } else { 2112 } else {
2113 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2113 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2114 } 2114 }
2115 frame_->Push(r0); 2115 frame_->EmitPush(r0);
2116 2116
2117 } else { 2117 } else {
2118 // Note: We would like to keep the assert below, but it fires because of 2118 // Note: We would like to keep the assert below, but it fires because of
2119 // some nasty code in LoadTypeofExpression() which should be removed... 2119 // some nasty code in LoadTypeofExpression() which should be removed...
2120 // ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2120 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2121 2121
2122 // Special handling for locals allocated in registers. 2122 // Special handling for locals allocated in registers.
2123 __ ldr(r0, SlotOperand(slot, r2)); 2123 __ ldr(r0, SlotOperand(slot, r2));
2124 frame_->Push(r0); 2124 frame_->EmitPush(r0);
2125 if (slot->var()->mode() == Variable::CONST) { 2125 if (slot->var()->mode() == Variable::CONST) {
2126 // Const slots may contain 'the hole' value (the constant hasn't been 2126 // Const slots may contain 'the hole' value (the constant hasn't been
2127 // initialized yet) which needs to be converted into the 'undefined' 2127 // initialized yet) which needs to be converted into the 'undefined'
2128 // value. 2128 // value.
2129 Comment cmnt(masm_, "[ Unhole const"); 2129 Comment cmnt(masm_, "[ Unhole const");
2130 frame_->Pop(r0); 2130 frame_->Pop(r0);
2131 __ cmp(r0, Operand(Factory::the_hole_value())); 2131 __ cmp(r0, Operand(Factory::the_hole_value()));
2132 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq); 2132 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
2133 frame_->Push(r0); 2133 frame_->EmitPush(r0);
2134 } 2134 }
2135 } 2135 }
2136 } 2136 }
2137 2137
2138 2138
2139 void CodeGenerator::VisitSlot(Slot* node) { 2139 void CodeGenerator::VisitSlot(Slot* node) {
2140 Comment cmnt(masm_, "[ Slot"); 2140 Comment cmnt(masm_, "[ Slot");
2141 LoadFromSlot(node, typeof_state()); 2141 LoadFromSlot(node, typeof_state());
2142 } 2142 }
2143 2143
2144 2144
2145 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2145 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2146 Comment cmnt(masm_, "[ VariableProxy"); 2146 Comment cmnt(masm_, "[ VariableProxy");
2147 2147
2148 Variable* var = node->var(); 2148 Variable* var = node->var();
2149 Expression* expr = var->rewrite(); 2149 Expression* expr = var->rewrite();
2150 if (expr != NULL) { 2150 if (expr != NULL) {
2151 Visit(expr); 2151 Visit(expr);
2152 } else { 2152 } else {
2153 ASSERT(var->is_global()); 2153 ASSERT(var->is_global());
2154 Reference ref(this, node); 2154 Reference ref(this, node);
2155 ref.GetValue(typeof_state()); 2155 ref.GetValue(typeof_state());
2156 } 2156 }
2157 } 2157 }
2158 2158
2159 2159
2160 void CodeGenerator::VisitLiteral(Literal* node) { 2160 void CodeGenerator::VisitLiteral(Literal* node) {
2161 Comment cmnt(masm_, "[ Literal"); 2161 Comment cmnt(masm_, "[ Literal");
2162 __ mov(r0, Operand(node->handle())); 2162 __ mov(r0, Operand(node->handle()));
2163 frame_->Push(r0); 2163 frame_->EmitPush(r0);
2164 } 2164 }
2165 2165
2166 2166
2167 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2167 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
2168 Comment cmnt(masm_, "[ RexExp Literal"); 2168 Comment cmnt(masm_, "[ RexExp Literal");
2169 2169
2170 // Retrieve the literal array and check the allocated entry. 2170 // Retrieve the literal array and check the allocated entry.
2171 2171
2172 // Load the function of this activation. 2172 // Load the function of this activation.
2173 __ ldr(r1, frame_->Function()); 2173 __ ldr(r1, frame_->Function());
2174 2174
2175 // Load the literals array of the function. 2175 // Load the literals array of the function.
2176 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 2176 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
2177 2177
2178 // Load the literal at the ast saved index. 2178 // Load the literal at the ast saved index.
2179 int literal_offset = 2179 int literal_offset =
2180 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2180 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2181 __ ldr(r2, FieldMemOperand(r1, literal_offset)); 2181 __ ldr(r2, FieldMemOperand(r1, literal_offset));
2182 2182
2183 JumpTarget done(this); 2183 JumpTarget done(this);
2184 __ cmp(r2, Operand(Factory::undefined_value())); 2184 __ cmp(r2, Operand(Factory::undefined_value()));
2185 done.Branch(ne); 2185 done.Branch(ne);
2186 2186
2187 // If the entry is undefined we call the runtime system to computed 2187 // If the entry is undefined we call the runtime system to computed
2188 // the literal. 2188 // the literal.
2189 frame_->Push(r1); // literal array (0) 2189 frame_->EmitPush(r1); // literal array (0)
2190 __ mov(r0, Operand(Smi::FromInt(node->literal_index()))); 2190 __ mov(r0, Operand(Smi::FromInt(node->literal_index())));
2191 frame_->Push(r0); // literal index (1) 2191 frame_->EmitPush(r0); // literal index (1)
2192 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2) 2192 __ mov(r0, Operand(node->pattern())); // RegExp pattern (2)
2193 frame_->Push(r0); 2193 frame_->EmitPush(r0);
2194 __ mov(r0, Operand(node->flags())); // RegExp flags (3) 2194 __ mov(r0, Operand(node->flags())); // RegExp flags (3)
2195 frame_->Push(r0); 2195 frame_->EmitPush(r0);
2196 frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 2196 frame_->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
2197 __ mov(r2, Operand(r0)); 2197 __ mov(r2, Operand(r0));
2198 2198
2199 done.Bind(); 2199 done.Bind();
2200 // Push the literal. 2200 // Push the literal.
2201 frame_->Push(r2); 2201 frame_->EmitPush(r2);
2202 } 2202 }
2203 2203
2204 2204
2205 // This deferred code stub will be used for creating the boilerplate 2205 // This deferred code stub will be used for creating the boilerplate
2206 // by calling Runtime_CreateObjectLiteral. 2206 // by calling Runtime_CreateObjectLiteral.
2207 // Each created boilerplate is stored in the JSFunction and they are 2207 // Each created boilerplate is stored in the JSFunction and they are
2208 // therefore context dependent. 2208 // therefore context dependent.
2209 class ObjectLiteralDeferred: public DeferredCode { 2209 class ObjectLiteralDeferred: public DeferredCode {
2210 public: 2210 public:
2211 ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node) 2211 ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2253 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2253 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2254 __ ldr(r2, FieldMemOperand(r1, literal_offset)); 2254 __ ldr(r2, FieldMemOperand(r1, literal_offset));
2255 2255
2256 // Check whether we need to materialize the object literal boilerplate. 2256 // Check whether we need to materialize the object literal boilerplate.
2257 // If so, jump to the deferred code. 2257 // If so, jump to the deferred code.
2258 __ cmp(r2, Operand(Factory::undefined_value())); 2258 __ cmp(r2, Operand(Factory::undefined_value()));
2259 __ b(eq, deferred->enter()); 2259 __ b(eq, deferred->enter());
2260 __ bind(deferred->exit()); 2260 __ bind(deferred->exit());
2261 2261
2262 // Push the object literal boilerplate. 2262 // Push the object literal boilerplate.
2263 frame_->Push(r2); 2263 frame_->EmitPush(r2);
2264 2264
2265 // Clone the boilerplate object. 2265 // Clone the boilerplate object.
2266 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); 2266 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
2267 frame_->Push(r0); // save the result 2267 frame_->EmitPush(r0); // save the result
2268 // r0: cloned object literal 2268 // r0: cloned object literal
2269 2269
2270 for (int i = 0; i < node->properties()->length(); i++) { 2270 for (int i = 0; i < node->properties()->length(); i++) {
2271 ObjectLiteral::Property* property = node->properties()->at(i); 2271 ObjectLiteral::Property* property = node->properties()->at(i);
2272 Literal* key = property->key(); 2272 Literal* key = property->key();
2273 Expression* value = property->value(); 2273 Expression* value = property->value();
2274 switch (property->kind()) { 2274 switch (property->kind()) {
2275 case ObjectLiteral::Property::CONSTANT: break; 2275 case ObjectLiteral::Property::CONSTANT: break;
2276 case ObjectLiteral::Property::COMPUTED: // fall through 2276 case ObjectLiteral::Property::COMPUTED: // fall through
2277 case ObjectLiteral::Property::PROTOTYPE: { 2277 case ObjectLiteral::Property::PROTOTYPE: {
2278 frame_->Push(r0); // dup the result 2278 frame_->EmitPush(r0); // dup the result
2279 Load(key); 2279 Load(key);
2280 Load(value); 2280 Load(value);
2281 frame_->CallRuntime(Runtime::kSetProperty, 3); 2281 frame_->CallRuntime(Runtime::kSetProperty, 3);
2282 // restore r0 2282 // restore r0
2283 __ ldr(r0, frame_->Top()); 2283 __ ldr(r0, frame_->Top());
2284 break; 2284 break;
2285 } 2285 }
2286 case ObjectLiteral::Property::SETTER: { 2286 case ObjectLiteral::Property::SETTER: {
2287 frame_->Push(r0); 2287 frame_->EmitPush(r0);
2288 Load(key); 2288 Load(key);
2289 __ mov(r0, Operand(Smi::FromInt(1))); 2289 __ mov(r0, Operand(Smi::FromInt(1)));
2290 frame_->Push(r0); 2290 frame_->EmitPush(r0);
2291 Load(value); 2291 Load(value);
2292 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2292 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2293 __ ldr(r0, frame_->Top()); 2293 __ ldr(r0, frame_->Top());
2294 break; 2294 break;
2295 } 2295 }
2296 case ObjectLiteral::Property::GETTER: { 2296 case ObjectLiteral::Property::GETTER: {
2297 frame_->Push(r0); 2297 frame_->EmitPush(r0);
2298 Load(key); 2298 Load(key);
2299 __ mov(r0, Operand(Smi::FromInt(0))); 2299 __ mov(r0, Operand(Smi::FromInt(0)));
2300 frame_->Push(r0); 2300 frame_->EmitPush(r0);
2301 Load(value); 2301 Load(value);
2302 frame_->CallRuntime(Runtime::kDefineAccessor, 4); 2302 frame_->CallRuntime(Runtime::kDefineAccessor, 4);
2303 __ ldr(r0, frame_->Top()); 2303 __ ldr(r0, frame_->Top());
2304 break; 2304 break;
2305 } 2305 }
2306 } 2306 }
2307 } 2307 }
2308 } 2308 }
2309 2309
2310 2310
2311 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2311 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2312 Comment cmnt(masm_, "[ ArrayLiteral"); 2312 Comment cmnt(masm_, "[ ArrayLiteral");
2313 2313
2314 // Call runtime to create the array literal. 2314 // Call runtime to create the array literal.
2315 __ mov(r0, Operand(node->literals())); 2315 __ mov(r0, Operand(node->literals()));
2316 frame_->Push(r0); 2316 frame_->EmitPush(r0);
2317 // Load the function of this frame. 2317 // Load the function of this frame.
2318 __ ldr(r0, frame_->Function()); 2318 __ ldr(r0, frame_->Function());
2319 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 2319 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
2320 frame_->Push(r0); 2320 frame_->EmitPush(r0);
2321 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2); 2321 frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2);
2322 2322
2323 // Push the resulting array literal on the stack. 2323 // Push the resulting array literal on the stack.
2324 frame_->Push(r0); 2324 frame_->EmitPush(r0);
2325 2325
2326 // Generate code to set the elements in the array that are not 2326 // Generate code to set the elements in the array that are not
2327 // literals. 2327 // literals.
2328 for (int i = 0; i < node->values()->length(); i++) { 2328 for (int i = 0; i < node->values()->length(); i++) {
2329 Expression* value = node->values()->at(i); 2329 Expression* value = node->values()->at(i);
2330 2330
2331 // If value is literal the property value is already 2331 // If value is literal the property value is already
2332 // set in the boilerplate object. 2332 // set in the boilerplate object.
2333 if (value->AsLiteral() == NULL) { 2333 if (value->AsLiteral() == NULL) {
2334 // The property must be set by generated code. 2334 // The property must be set by generated code.
(...skipping 19 matching lines...) Expand all
2354 2354
2355 void CodeGenerator::VisitAssignment(Assignment* node) { 2355 void CodeGenerator::VisitAssignment(Assignment* node) {
2356 Comment cmnt(masm_, "[ Assignment"); 2356 Comment cmnt(masm_, "[ Assignment");
2357 if (FLAG_debug_info) RecordStatementPosition(node); 2357 if (FLAG_debug_info) RecordStatementPosition(node);
2358 2358
2359 Reference target(this, node->target()); 2359 Reference target(this, node->target());
2360 if (target.is_illegal()) { 2360 if (target.is_illegal()) {
2361 // Fool the virtual frame into thinking that we left the assignment's 2361 // Fool the virtual frame into thinking that we left the assignment's
2362 // value on the frame. 2362 // value on the frame.
2363 __ mov(r0, Operand(Smi::FromInt(0))); 2363 __ mov(r0, Operand(Smi::FromInt(0)));
2364 frame_->Push(r0); 2364 frame_->EmitPush(r0);
2365 return; 2365 return;
2366 } 2366 }
2367 2367
2368 if (node->op() == Token::ASSIGN || 2368 if (node->op() == Token::ASSIGN ||
2369 node->op() == Token::INIT_VAR || 2369 node->op() == Token::INIT_VAR ||
2370 node->op() == Token::INIT_CONST) { 2370 node->op() == Token::INIT_CONST) {
2371 Load(node->value()); 2371 Load(node->value());
2372 2372
2373 } else { 2373 } else {
2374 target.GetValue(NOT_INSIDE_TYPEOF); 2374 target.GetValue(NOT_INSIDE_TYPEOF);
2375 Literal* literal = node->value()->AsLiteral(); 2375 Literal* literal = node->value()->AsLiteral();
2376 if (literal != NULL && literal->handle()->IsSmi()) { 2376 if (literal != NULL && literal->handle()->IsSmi()) {
2377 SmiOperation(node->binary_op(), literal->handle(), false); 2377 SmiOperation(node->binary_op(), literal->handle(), false);
2378 frame_->Push(r0); 2378 frame_->EmitPush(r0);
2379 2379
2380 } else { 2380 } else {
2381 Load(node->value()); 2381 Load(node->value());
2382 GenericBinaryOperation(node->binary_op()); 2382 GenericBinaryOperation(node->binary_op());
2383 frame_->Push(r0); 2383 frame_->EmitPush(r0);
2384 } 2384 }
2385 } 2385 }
2386 2386
2387 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 2387 Variable* var = node->target()->AsVariableProxy()->AsVariable();
2388 if (var != NULL && 2388 if (var != NULL &&
2389 (var->mode() == Variable::CONST) && 2389 (var->mode() == Variable::CONST) &&
2390 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 2390 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
2391 // Assignment ignored - leave the value on the stack. 2391 // Assignment ignored - leave the value on the stack.
2392 2392
2393 } else { 2393 } else {
2394 __ RecordPosition(node->position()); 2394 __ RecordPosition(node->position());
2395 if (node->op() == Token::INIT_CONST) { 2395 if (node->op() == Token::INIT_CONST) {
2396 // Dynamic constant initializations must use the function context 2396 // Dynamic constant initializations must use the function context
2397 // and initialize the actual constant declared. Dynamic variable 2397 // and initialize the actual constant declared. Dynamic variable
2398 // initializations are simply assignments and use SetValue. 2398 // initializations are simply assignments and use SetValue.
2399 target.SetValue(CONST_INIT); 2399 target.SetValue(CONST_INIT);
2400 } else { 2400 } else {
2401 target.SetValue(NOT_CONST_INIT); 2401 target.SetValue(NOT_CONST_INIT);
2402 } 2402 }
2403 } 2403 }
2404 } 2404 }
2405 2405
2406 2406
2407 void CodeGenerator::VisitThrow(Throw* node) { 2407 void CodeGenerator::VisitThrow(Throw* node) {
2408 Comment cmnt(masm_, "[ Throw"); 2408 Comment cmnt(masm_, "[ Throw");
2409 2409
2410 Load(node->exception()); 2410 Load(node->exception());
2411 __ RecordPosition(node->position()); 2411 __ RecordPosition(node->position());
2412 frame_->CallRuntime(Runtime::kThrow, 1); 2412 frame_->CallRuntime(Runtime::kThrow, 1);
2413 frame_->Push(r0); 2413 frame_->EmitPush(r0);
2414 } 2414 }
2415 2415
2416 2416
2417 void CodeGenerator::VisitProperty(Property* node) { 2417 void CodeGenerator::VisitProperty(Property* node) {
2418 Comment cmnt(masm_, "[ Property"); 2418 Comment cmnt(masm_, "[ Property");
2419 2419
2420 Reference property(this, node); 2420 Reference property(this, node);
2421 property.GetValue(typeof_state()); 2421 property.GetValue(typeof_state());
2422 } 2422 }
2423 2423
(...skipping 20 matching lines...) Expand all
2444 // is resolved in cache misses (this also holds for megamorphic calls). 2444 // is resolved in cache misses (this also holds for megamorphic calls).
2445 // ------------------------------------------------------------------------ 2445 // ------------------------------------------------------------------------
2446 2446
2447 if (var != NULL && !var->is_this() && var->is_global()) { 2447 if (var != NULL && !var->is_this() && var->is_global()) {
2448 // ---------------------------------- 2448 // ----------------------------------
2449 // JavaScript example: 'foo(1, 2, 3)' // foo is global 2449 // JavaScript example: 'foo(1, 2, 3)' // foo is global
2450 // ---------------------------------- 2450 // ----------------------------------
2451 2451
2452 // Push the name of the function and the receiver onto the stack. 2452 // Push the name of the function and the receiver onto the stack.
2453 __ mov(r0, Operand(var->name())); 2453 __ mov(r0, Operand(var->name()));
2454 frame_->Push(r0); 2454 frame_->EmitPush(r0);
2455 2455
2456 // Pass the global object as the receiver and let the IC stub 2456 // Pass the global object as the receiver and let the IC stub
2457 // patch the stack to use the global proxy as 'this' in the 2457 // patch the stack to use the global proxy as 'this' in the
2458 // invoked function. 2458 // invoked function.
2459 LoadGlobal(); 2459 LoadGlobal();
2460 2460
2461 // Load the arguments. 2461 // Load the arguments.
2462 int arg_count = args->length(); 2462 int arg_count = args->length();
2463 for (int i = 0; i < arg_count; i++) { 2463 for (int i = 0; i < arg_count; i++) {
2464 Load(args->at(i)); 2464 Load(args->at(i));
2465 } 2465 }
2466 2466
2467 // Setup the receiver register and call the IC initialization code. 2467 // Setup the receiver register and call the IC initialization code.
2468 Handle<Code> stub = ComputeCallInitialize(arg_count); 2468 Handle<Code> stub = ComputeCallInitialize(arg_count);
2469 __ RecordPosition(node->position()); 2469 __ RecordPosition(node->position());
2470 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, 2470 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
2471 arg_count + 1); 2471 arg_count + 1);
2472 __ ldr(cp, frame_->Context()); 2472 __ ldr(cp, frame_->Context());
2473 // Remove the function from the stack. 2473 // Remove the function from the stack.
2474 frame_->Drop(); 2474 frame_->Drop();
2475 frame_->Push(r0); 2475 frame_->EmitPush(r0);
2476 2476
2477 } else if (var != NULL && var->slot() != NULL && 2477 } else if (var != NULL && var->slot() != NULL &&
2478 var->slot()->type() == Slot::LOOKUP) { 2478 var->slot()->type() == Slot::LOOKUP) {
2479 // ---------------------------------- 2479 // ----------------------------------
2480 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 2480 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
2481 // ---------------------------------- 2481 // ----------------------------------
2482 2482
2483 // Load the function 2483 // Load the function
2484 frame_->Push(cp); 2484 frame_->EmitPush(cp);
2485 __ mov(r0, Operand(var->name())); 2485 __ mov(r0, Operand(var->name()));
2486 frame_->Push(r0); 2486 frame_->EmitPush(r0);
2487 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2487 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2488 // r0: slot value; r1: receiver 2488 // r0: slot value; r1: receiver
2489 2489
2490 // Load the receiver. 2490 // Load the receiver.
2491 frame_->Push(r0); // function 2491 frame_->EmitPush(r0); // function
2492 frame_->Push(r1); // receiver 2492 frame_->EmitPush(r1); // receiver
2493 2493
2494 // Call the function. 2494 // Call the function.
2495 CallWithArguments(args, node->position()); 2495 CallWithArguments(args, node->position());
2496 frame_->Push(r0); 2496 frame_->EmitPush(r0);
2497 2497
2498 } else if (property != NULL) { 2498 } else if (property != NULL) {
2499 // Check if the key is a literal string. 2499 // Check if the key is a literal string.
2500 Literal* literal = property->key()->AsLiteral(); 2500 Literal* literal = property->key()->AsLiteral();
2501 2501
2502 if (literal != NULL && literal->handle()->IsSymbol()) { 2502 if (literal != NULL && literal->handle()->IsSymbol()) {
2503 // ------------------------------------------------------------------ 2503 // ------------------------------------------------------------------
2504 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2504 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2505 // ------------------------------------------------------------------ 2505 // ------------------------------------------------------------------
2506 2506
2507 // Push the name of the function and the receiver onto the stack. 2507 // Push the name of the function and the receiver onto the stack.
2508 __ mov(r0, Operand(literal->handle())); 2508 __ mov(r0, Operand(literal->handle()));
2509 frame_->Push(r0); 2509 frame_->EmitPush(r0);
2510 Load(property->obj()); 2510 Load(property->obj());
2511 2511
2512 // Load the arguments. 2512 // Load the arguments.
2513 int arg_count = args->length(); 2513 int arg_count = args->length();
2514 for (int i = 0; i < arg_count; i++) { 2514 for (int i = 0; i < arg_count; i++) {
2515 Load(args->at(i)); 2515 Load(args->at(i));
2516 } 2516 }
2517 2517
2518 // Set the receiver register and call the IC initialization code. 2518 // Set the receiver register and call the IC initialization code.
2519 Handle<Code> stub = ComputeCallInitialize(arg_count); 2519 Handle<Code> stub = ComputeCallInitialize(arg_count);
2520 __ RecordPosition(node->position()); 2520 __ RecordPosition(node->position());
2521 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 2521 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
2522 __ ldr(cp, frame_->Context()); 2522 __ ldr(cp, frame_->Context());
2523 2523
2524 // Remove the function from the stack. 2524 // Remove the function from the stack.
2525 frame_->Drop(); 2525 frame_->Drop();
2526 2526
2527 frame_->Push(r0); // push after get rid of function from the stack 2527 frame_->EmitPush(r0); // push after get rid of function from the stack
2528 2528
2529 } else { 2529 } else {
2530 // ------------------------------------------- 2530 // -------------------------------------------
2531 // JavaScript example: 'array[index](1, 2, 3)' 2531 // JavaScript example: 'array[index](1, 2, 3)'
2532 // ------------------------------------------- 2532 // -------------------------------------------
2533 2533
2534 // Load the function to call from the property through a reference. 2534 // Load the function to call from the property through a reference.
2535 Reference ref(this, property); 2535 Reference ref(this, property);
2536 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver 2536 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver
2537 2537
2538 // Pass receiver to called function. 2538 // Pass receiver to called function.
2539 __ ldr(r0, frame_->ElementAt(ref.size())); 2539 __ ldr(r0, frame_->ElementAt(ref.size()));
2540 frame_->Push(r0); 2540 frame_->EmitPush(r0);
2541 // Call the function. 2541 // Call the function.
2542 CallWithArguments(args, node->position()); 2542 CallWithArguments(args, node->position());
2543 frame_->Push(r0); 2543 frame_->EmitPush(r0);
2544 } 2544 }
2545 2545
2546 } else { 2546 } else {
2547 // ---------------------------------- 2547 // ----------------------------------
2548 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2548 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2549 // ---------------------------------- 2549 // ----------------------------------
2550 2550
2551 // Load the function. 2551 // Load the function.
2552 Load(function); 2552 Load(function);
2553 2553
2554 // Pass the global proxy as the receiver. 2554 // Pass the global proxy as the receiver.
2555 LoadGlobalReceiver(r0); 2555 LoadGlobalReceiver(r0);
2556 2556
2557 // Call the function. 2557 // Call the function.
2558 CallWithArguments(args, node->position()); 2558 CallWithArguments(args, node->position());
2559 frame_->Push(r0); 2559 frame_->EmitPush(r0);
2560 } 2560 }
2561 } 2561 }
2562 2562
2563 2563
2564 void CodeGenerator::VisitCallNew(CallNew* node) { 2564 void CodeGenerator::VisitCallNew(CallNew* node) {
2565 Comment cmnt(masm_, "[ CallNew"); 2565 Comment cmnt(masm_, "[ CallNew");
2566 2566
2567 // According to ECMA-262, section 11.2.2, page 44, the function 2567 // According to ECMA-262, section 11.2.2, page 44, the function
2568 // expression in new calls must be evaluated before the 2568 // expression in new calls must be evaluated before the
2569 // arguments. This is different from ordinary calls, where the 2569 // arguments. This is different from ordinary calls, where the
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 leave.Branch(eq); 2610 leave.Branch(eq);
2611 // It is a heap object - get map. 2611 // It is a heap object - get map.
2612 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2612 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2613 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 2613 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2614 // if (!object->IsJSValue()) return the object. 2614 // if (!object->IsJSValue()) return the object.
2615 __ cmp(r1, Operand(JS_VALUE_TYPE)); 2615 __ cmp(r1, Operand(JS_VALUE_TYPE));
2616 leave.Branch(ne); 2616 leave.Branch(ne);
2617 // Load the value. 2617 // Load the value.
2618 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 2618 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
2619 leave.Bind(); 2619 leave.Bind();
2620 frame_->Push(r0); 2620 frame_->EmitPush(r0);
2621 } 2621 }
2622 2622
2623 2623
2624 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 2624 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
2625 ASSERT(args->length() == 2); 2625 ASSERT(args->length() == 2);
2626 JumpTarget leave(this); 2626 JumpTarget leave(this);
2627 Load(args->at(0)); // Load the object. 2627 Load(args->at(0)); // Load the object.
2628 Load(args->at(1)); // Load the value. 2628 Load(args->at(1)); // Load the value.
2629 frame_->Pop(r0); // r0 contains value 2629 frame_->Pop(r0); // r0 contains value
2630 frame_->Pop(r1); // r1 contains object 2630 frame_->Pop(r1); // r1 contains object
2631 // if (object->IsSmi()) return object. 2631 // if (object->IsSmi()) return object.
2632 __ tst(r1, Operand(kSmiTagMask)); 2632 __ tst(r1, Operand(kSmiTagMask));
2633 leave.Branch(eq); 2633 leave.Branch(eq);
2634 // It is a heap object - get map. 2634 // It is a heap object - get map.
2635 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 2635 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
2636 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 2636 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
2637 // if (!object->IsJSValue()) return object. 2637 // if (!object->IsJSValue()) return object.
2638 __ cmp(r2, Operand(JS_VALUE_TYPE)); 2638 __ cmp(r2, Operand(JS_VALUE_TYPE));
2639 leave.Branch(ne); 2639 leave.Branch(ne);
2640 // Store the value. 2640 // Store the value.
2641 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 2641 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
2642 // Update the write barrier. 2642 // Update the write barrier.
2643 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); 2643 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
2644 __ RecordWrite(r1, r2, r3); 2644 __ RecordWrite(r1, r2, r3);
2645 // Leave. 2645 // Leave.
2646 leave.Bind(); 2646 leave.Bind();
2647 frame_->Push(r0); 2647 frame_->EmitPush(r0);
2648 } 2648 }
2649 2649
2650 2650
2651 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 2651 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
2652 ASSERT(args->length() == 1); 2652 ASSERT(args->length() == 1);
2653 Load(args->at(0)); 2653 Load(args->at(0));
2654 frame_->Pop(r0); 2654 frame_->Pop(r0);
2655 __ tst(r0, Operand(kSmiTagMask)); 2655 __ tst(r0, Operand(kSmiTagMask));
2656 cc_reg_ = eq; 2656 cc_reg_ = eq;
2657 } 2657 }
2658 2658
2659 2659
2660 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 2660 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
2661 ASSERT(args->length() == 1); 2661 ASSERT(args->length() == 1);
2662 Load(args->at(0)); 2662 Load(args->at(0));
2663 frame_->Pop(r0); 2663 frame_->Pop(r0);
2664 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 2664 __ tst(r0, Operand(kSmiTagMask | 0x80000000));
2665 cc_reg_ = eq; 2665 cc_reg_ = eq;
2666 } 2666 }
2667 2667
2668 2668
2669 // This should generate code that performs a charCodeAt() call or returns 2669 // This should generate code that performs a charCodeAt() call or returns
2670 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 2670 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
2671 // It is not yet implemented on ARM, so it always goes to the slow case. 2671 // It is not yet implemented on ARM, so it always goes to the slow case.
2672 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 2672 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
2673 ASSERT(args->length() == 2); 2673 ASSERT(args->length() == 2);
2674 __ mov(r0, Operand(Factory::undefined_value())); 2674 __ mov(r0, Operand(Factory::undefined_value()));
2675 frame_->Push(r0); 2675 frame_->EmitPush(r0);
2676 } 2676 }
2677 2677
2678 2678
2679 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 2679 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
2680 ASSERT(args->length() == 1); 2680 ASSERT(args->length() == 1);
2681 Load(args->at(0)); 2681 Load(args->at(0));
2682 JumpTarget answer(this); 2682 JumpTarget answer(this);
2683 // We need the CC bits to come out as not_equal in the case where the 2683 // We need the CC bits to come out as not_equal in the case where the
2684 // object is a smi. This can't be done with the usual test opcode so 2684 // object is a smi. This can't be done with the usual test opcode so
2685 // we use XOR to get the right CC bits. 2685 // we use XOR to get the right CC bits.
(...skipping 14 matching lines...) Expand all
2700 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 2700 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
2701 ASSERT(args->length() == 0); 2701 ASSERT(args->length() == 0);
2702 2702
2703 // Seed the result with the formal parameters count, which will be used 2703 // Seed the result with the formal parameters count, which will be used
2704 // in case no arguments adaptor frame is found below the current frame. 2704 // in case no arguments adaptor frame is found below the current frame.
2705 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); 2705 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
2706 2706
2707 // Call the shared stub to get to the arguments.length. 2707 // Call the shared stub to get to the arguments.length.
2708 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); 2708 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
2709 frame_->CallStub(&stub, 0); 2709 frame_->CallStub(&stub, 0);
2710 frame_->Push(r0); 2710 frame_->EmitPush(r0);
2711 } 2711 }
2712 2712
2713 2713
2714 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 2714 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
2715 ASSERT(args->length() == 1); 2715 ASSERT(args->length() == 1);
2716 2716
2717 // Satisfy contract with ArgumentsAccessStub: 2717 // Satisfy contract with ArgumentsAccessStub:
2718 // Load the key into r1 and the formal parameters count into r0. 2718 // Load the key into r1 and the formal parameters count into r0.
2719 Load(args->at(0)); 2719 Load(args->at(0));
2720 frame_->Pop(r1); 2720 frame_->Pop(r1);
2721 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); 2721 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
2722 2722
2723 // Call the shared stub to get to arguments[key]. 2723 // Call the shared stub to get to arguments[key].
2724 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2724 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2725 frame_->CallStub(&stub, 0); 2725 frame_->CallStub(&stub, 0);
2726 frame_->Push(r0); 2726 frame_->EmitPush(r0);
2727 } 2727 }
2728 2728
2729 2729
2730 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 2730 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
2731 ASSERT(args->length() == 2); 2731 ASSERT(args->length() == 2);
2732 2732
2733 // Load the two objects into registers and perform the comparison. 2733 // Load the two objects into registers and perform the comparison.
2734 Load(args->at(0)); 2734 Load(args->at(0));
2735 Load(args->at(1)); 2735 Load(args->at(1));
2736 frame_->Pop(r0); 2736 frame_->Pop(r0);
(...skipping 14 matching lines...) Expand all
2751 2751
2752 if (function != NULL) { 2752 if (function != NULL) {
2753 // Push the arguments ("left-to-right"). 2753 // Push the arguments ("left-to-right").
2754 int arg_count = args->length(); 2754 int arg_count = args->length();
2755 for (int i = 0; i < arg_count; i++) { 2755 for (int i = 0; i < arg_count; i++) {
2756 Load(args->at(i)); 2756 Load(args->at(i));
2757 } 2757 }
2758 2758
2759 // Call the C runtime function. 2759 // Call the C runtime function.
2760 frame_->CallRuntime(function, arg_count); 2760 frame_->CallRuntime(function, arg_count);
2761 frame_->Push(r0); 2761 frame_->EmitPush(r0);
2762 2762
2763 } else { 2763 } else {
2764 // Prepare stack for calling JS runtime function. 2764 // Prepare stack for calling JS runtime function.
2765 __ mov(r0, Operand(node->name())); 2765 __ mov(r0, Operand(node->name()));
2766 frame_->Push(r0); 2766 frame_->EmitPush(r0);
2767 // Push the builtins object found in the current global object. 2767 // Push the builtins object found in the current global object.
2768 __ ldr(r1, GlobalObject()); 2768 __ ldr(r1, GlobalObject());
2769 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); 2769 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
2770 frame_->Push(r0); 2770 frame_->EmitPush(r0);
2771 2771
2772 int arg_count = args->length(); 2772 int arg_count = args->length();
2773 for (int i = 0; i < arg_count; i++) { 2773 for (int i = 0; i < arg_count; i++) {
2774 Load(args->at(i)); 2774 Load(args->at(i));
2775 } 2775 }
2776 2776
2777 // Call the JS runtime function. 2777 // Call the JS runtime function.
2778 Handle<Code> stub = ComputeCallInitialize(args->length()); 2778 Handle<Code> stub = ComputeCallInitialize(args->length());
2779 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 2779 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
2780 __ ldr(cp, frame_->Context()); 2780 __ ldr(cp, frame_->Context());
2781 frame_->Drop(); 2781 frame_->Drop();
2782 frame_->Push(r0); 2782 frame_->EmitPush(r0);
2783 } 2783 }
2784 } 2784 }
2785 2785
2786 2786
2787 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 2787 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
2788 Comment cmnt(masm_, "[ UnaryOperation"); 2788 Comment cmnt(masm_, "[ UnaryOperation");
2789 2789
2790 Token::Value op = node->op(); 2790 Token::Value op = node->op();
2791 2791
2792 if (op == Token::NOT) { 2792 if (op == Token::NOT) {
(...skipping 11 matching lines...) Expand all
2804 Load(property->obj()); 2804 Load(property->obj());
2805 Load(property->key()); 2805 Load(property->key());
2806 __ mov(r0, Operand(1)); // not counting receiver 2806 __ mov(r0, Operand(1)); // not counting receiver
2807 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); 2807 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
2808 2808
2809 } else if (variable != NULL) { 2809 } else if (variable != NULL) {
2810 Slot* slot = variable->slot(); 2810 Slot* slot = variable->slot();
2811 if (variable->is_global()) { 2811 if (variable->is_global()) {
2812 LoadGlobal(); 2812 LoadGlobal();
2813 __ mov(r0, Operand(variable->name())); 2813 __ mov(r0, Operand(variable->name()));
2814 frame_->Push(r0); 2814 frame_->EmitPush(r0);
2815 __ mov(r0, Operand(1)); // not counting receiver 2815 __ mov(r0, Operand(1)); // not counting receiver
2816 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); 2816 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
2817 2817
2818 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 2818 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
2819 // lookup the context holding the named variable 2819 // lookup the context holding the named variable
2820 frame_->Push(cp); 2820 frame_->EmitPush(cp);
2821 __ mov(r0, Operand(variable->name())); 2821 __ mov(r0, Operand(variable->name()));
2822 frame_->Push(r0); 2822 frame_->EmitPush(r0);
2823 frame_->CallRuntime(Runtime::kLookupContext, 2); 2823 frame_->CallRuntime(Runtime::kLookupContext, 2);
2824 // r0: context 2824 // r0: context
2825 frame_->Push(r0); 2825 frame_->EmitPush(r0);
2826 __ mov(r0, Operand(variable->name())); 2826 __ mov(r0, Operand(variable->name()));
2827 frame_->Push(r0); 2827 frame_->EmitPush(r0);
2828 __ mov(r0, Operand(1)); // not counting receiver 2828 __ mov(r0, Operand(1)); // not counting receiver
2829 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); 2829 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2);
2830 2830
2831 } else { 2831 } else {
2832 // Default: Result of deleting non-global, not dynamically 2832 // Default: Result of deleting non-global, not dynamically
2833 // introduced variables is false. 2833 // introduced variables is false.
2834 __ mov(r0, Operand(Factory::false_value())); 2834 __ mov(r0, Operand(Factory::false_value()));
2835 } 2835 }
2836 2836
2837 } else { 2837 } else {
2838 // Default: Result of deleting expressions is true. 2838 // Default: Result of deleting expressions is true.
2839 Load(node->expression()); // may have side-effects 2839 Load(node->expression()); // may have side-effects
2840 frame_->Drop(); 2840 frame_->Drop();
2841 __ mov(r0, Operand(Factory::true_value())); 2841 __ mov(r0, Operand(Factory::true_value()));
2842 } 2842 }
2843 frame_->Push(r0); 2843 frame_->EmitPush(r0);
2844 2844
2845 } else if (op == Token::TYPEOF) { 2845 } else if (op == Token::TYPEOF) {
2846 // Special case for loading the typeof expression; see comment on 2846 // Special case for loading the typeof expression; see comment on
2847 // LoadTypeofExpression(). 2847 // LoadTypeofExpression().
2848 LoadTypeofExpression(node->expression()); 2848 LoadTypeofExpression(node->expression());
2849 frame_->CallRuntime(Runtime::kTypeof, 1); 2849 frame_->CallRuntime(Runtime::kTypeof, 1);
2850 frame_->Push(r0); // r0 has result 2850 frame_->EmitPush(r0); // r0 has result
2851 2851
2852 } else { 2852 } else {
2853 Load(node->expression()); 2853 Load(node->expression());
2854 frame_->Pop(r0); 2854 frame_->Pop(r0);
2855 switch (op) { 2855 switch (op) {
2856 case Token::NOT: 2856 case Token::NOT:
2857 case Token::DELETE: 2857 case Token::DELETE:
2858 case Token::TYPEOF: 2858 case Token::TYPEOF:
2859 UNREACHABLE(); // handled above 2859 UNREACHABLE(); // handled above
2860 break; 2860 break;
2861 2861
2862 case Token::SUB: { 2862 case Token::SUB: {
2863 UnarySubStub stub; 2863 UnarySubStub stub;
2864 frame_->CallStub(&stub, 0); 2864 frame_->CallStub(&stub, 0);
2865 break; 2865 break;
2866 } 2866 }
2867 2867
2868 case Token::BIT_NOT: { 2868 case Token::BIT_NOT: {
2869 // smi check 2869 // smi check
2870 JumpTarget smi_label(this); 2870 JumpTarget smi_label(this);
2871 JumpTarget continue_label(this); 2871 JumpTarget continue_label(this);
2872 __ tst(r0, Operand(kSmiTagMask)); 2872 __ tst(r0, Operand(kSmiTagMask));
2873 smi_label.Branch(eq); 2873 smi_label.Branch(eq);
2874 2874
2875 frame_->Push(r0); 2875 frame_->EmitPush(r0);
2876 __ mov(r0, Operand(0)); // not counting receiver 2876 __ mov(r0, Operand(0)); // not counting receiver
2877 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, 1); 2877 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, 1);
2878 2878
2879 continue_label.Jump(); 2879 continue_label.Jump();
2880 smi_label.Bind(); 2880 smi_label.Bind();
2881 __ mvn(r0, Operand(r0)); 2881 __ mvn(r0, Operand(r0));
2882 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag 2882 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag
2883 continue_label.Bind(); 2883 continue_label.Bind();
2884 break; 2884 break;
2885 } 2885 }
2886 2886
2887 case Token::VOID: 2887 case Token::VOID:
2888 // since the stack top is cached in r0, popping and then 2888 // since the stack top is cached in r0, popping and then
2889 // pushing a value can be done by just writing to r0. 2889 // pushing a value can be done by just writing to r0.
2890 __ mov(r0, Operand(Factory::undefined_value())); 2890 __ mov(r0, Operand(Factory::undefined_value()));
2891 break; 2891 break;
2892 2892
2893 case Token::ADD: { 2893 case Token::ADD: {
2894 // Smi check. 2894 // Smi check.
2895 JumpTarget continue_label(this); 2895 JumpTarget continue_label(this);
2896 __ tst(r0, Operand(kSmiTagMask)); 2896 __ tst(r0, Operand(kSmiTagMask));
2897 continue_label.Branch(eq); 2897 continue_label.Branch(eq);
2898 frame_->Push(r0); 2898 frame_->EmitPush(r0);
2899 __ mov(r0, Operand(0)); // not counting receiver 2899 __ mov(r0, Operand(0)); // not counting receiver
2900 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); 2900 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1);
2901 continue_label.Bind(); 2901 continue_label.Bind();
2902 break; 2902 break;
2903 } 2903 }
2904 default: 2904 default:
2905 UNREACHABLE(); 2905 UNREACHABLE();
2906 } 2906 }
2907 frame_->Push(r0); // r0 has result 2907 frame_->EmitPush(r0); // r0 has result
2908 } 2908 }
2909 } 2909 }
2910 2910
2911 2911
2912 void CodeGenerator::VisitCountOperation(CountOperation* node) { 2912 void CodeGenerator::VisitCountOperation(CountOperation* node) {
2913 Comment cmnt(masm_, "[ CountOperation"); 2913 Comment cmnt(masm_, "[ CountOperation");
2914 2914
2915 bool is_postfix = node->is_postfix(); 2915 bool is_postfix = node->is_postfix();
2916 bool is_increment = node->op() == Token::INC; 2916 bool is_increment = node->op() == Token::INC;
2917 2917
2918 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 2918 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
2919 bool is_const = (var != NULL && var->mode() == Variable::CONST); 2919 bool is_const = (var != NULL && var->mode() == Variable::CONST);
2920 2920
2921 // Postfix: Make room for the result. 2921 // Postfix: Make room for the result.
2922 if (is_postfix) { 2922 if (is_postfix) {
2923 __ mov(r0, Operand(0)); 2923 __ mov(r0, Operand(0));
2924 frame_->Push(r0); 2924 frame_->EmitPush(r0);
2925 } 2925 }
2926 2926
2927 { Reference target(this, node->expression()); 2927 { Reference target(this, node->expression());
2928 if (target.is_illegal()) { 2928 if (target.is_illegal()) {
2929 // Spoof the virtual frame to have the expected height (one higher 2929 // Spoof the virtual frame to have the expected height (one higher
2930 // than on entry). 2930 // than on entry).
2931 if (!is_postfix) { 2931 if (!is_postfix) {
2932 __ mov(r0, Operand(Smi::FromInt(0))); 2932 __ mov(r0, Operand(Smi::FromInt(0)));
2933 frame_->Push(r0); 2933 frame_->EmitPush(r0);
2934 } 2934 }
2935 return; 2935 return;
2936 } 2936 }
2937 target.GetValue(NOT_INSIDE_TYPEOF); 2937 target.GetValue(NOT_INSIDE_TYPEOF);
2938 frame_->Pop(r0); 2938 frame_->Pop(r0);
2939 2939
2940 JumpTarget slow(this); 2940 JumpTarget slow(this);
2941 JumpTarget exit(this); 2941 JumpTarget exit(this);
2942 2942
2943 // Load the value (1) into register r1. 2943 // Load the value (1) into register r1.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2984 if (is_increment) { 2984 if (is_increment) {
2985 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1); 2985 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1);
2986 frame_->CallStub(&stub, 0); 2986 frame_->CallStub(&stub, 0);
2987 } else { 2987 } else {
2988 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1); 2988 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1);
2989 frame_->CallStub(&stub, 0); 2989 frame_->CallStub(&stub, 0);
2990 } 2990 }
2991 2991
2992 // Store the new value in the target if not const. 2992 // Store the new value in the target if not const.
2993 exit.Bind(); 2993 exit.Bind();
2994 frame_->Push(r0); 2994 frame_->EmitPush(r0);
2995 if (!is_const) target.SetValue(NOT_CONST_INIT); 2995 if (!is_const) target.SetValue(NOT_CONST_INIT);
2996 } 2996 }
2997 2997
2998 // Postfix: Discard the new value and use the old. 2998 // Postfix: Discard the new value and use the old.
2999 if (is_postfix) frame_->Pop(r0); 2999 if (is_postfix) frame_->Pop(r0);
3000 } 3000 }
3001 3001
3002 3002
3003 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { 3003 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
3004 Comment cmnt(masm_, "[ BinaryOperation"); 3004 Comment cmnt(masm_, "[ BinaryOperation");
(...skipping 27 matching lines...) Expand all
3032 NOT_INSIDE_TYPEOF, 3032 NOT_INSIDE_TYPEOF,
3033 true_target(), 3033 true_target(),
3034 false_target(), 3034 false_target(),
3035 false); 3035 false);
3036 3036
3037 } else { 3037 } else {
3038 JumpTarget pop_and_continue(this); 3038 JumpTarget pop_and_continue(this);
3039 JumpTarget exit(this); 3039 JumpTarget exit(this);
3040 3040
3041 __ ldr(r0, frame_->Top()); // dup the stack top 3041 __ ldr(r0, frame_->Top()); // dup the stack top
3042 frame_->Push(r0); 3042 frame_->EmitPush(r0);
3043 // Avoid popping the result if it converts to 'false' using the 3043 // Avoid popping the result if it converts to 'false' using the
3044 // standard ToBoolean() conversion as described in ECMA-262, 3044 // standard ToBoolean() conversion as described in ECMA-262,
3045 // section 9.2, page 30. 3045 // section 9.2, page 30.
3046 ToBoolean(&pop_and_continue, &exit); 3046 ToBoolean(&pop_and_continue, &exit);
3047 Branch(false, &exit); 3047 Branch(false, &exit);
3048 3048
3049 // Pop the result of evaluating the first part. 3049 // Pop the result of evaluating the first part.
3050 pop_and_continue.Bind(); 3050 pop_and_continue.Bind();
3051 frame_->Pop(r0); 3051 frame_->Pop(r0);
3052 3052
(...skipping 21 matching lines...) Expand all
3074 NOT_INSIDE_TYPEOF, 3074 NOT_INSIDE_TYPEOF,
3075 true_target(), 3075 true_target(),
3076 false_target(), 3076 false_target(),
3077 false); 3077 false);
3078 3078
3079 } else { 3079 } else {
3080 JumpTarget pop_and_continue(this); 3080 JumpTarget pop_and_continue(this);
3081 JumpTarget exit(this); 3081 JumpTarget exit(this);
3082 3082
3083 __ ldr(r0, frame_->Top()); 3083 __ ldr(r0, frame_->Top());
3084 frame_->Push(r0); 3084 frame_->EmitPush(r0);
3085 // Avoid popping the result if it converts to 'true' using the 3085 // Avoid popping the result if it converts to 'true' using the
3086 // standard ToBoolean() conversion as described in ECMA-262, 3086 // standard ToBoolean() conversion as described in ECMA-262,
3087 // section 9.2, page 30. 3087 // section 9.2, page 30.
3088 ToBoolean(&exit, &pop_and_continue); 3088 ToBoolean(&exit, &pop_and_continue);
3089 Branch(true, &exit); 3089 Branch(true, &exit);
3090 3090
3091 // Pop the result of evaluating the first part. 3091 // Pop the result of evaluating the first part.
3092 pop_and_continue.Bind(); 3092 pop_and_continue.Bind();
3093 frame_->Pop(r0); 3093 frame_->Pop(r0);
3094 3094
(...skipping 17 matching lines...) Expand all
3112 3112
3113 } else if (lliteral != NULL && lliteral->handle()->IsSmi()) { 3113 } else if (lliteral != NULL && lliteral->handle()->IsSmi()) {
3114 Load(node->right()); 3114 Load(node->right());
3115 SmiOperation(node->op(), lliteral->handle(), true); 3115 SmiOperation(node->op(), lliteral->handle(), true);
3116 3116
3117 } else { 3117 } else {
3118 Load(node->left()); 3118 Load(node->left());
3119 Load(node->right()); 3119 Load(node->right());
3120 GenericBinaryOperation(node->op()); 3120 GenericBinaryOperation(node->op());
3121 } 3121 }
3122 frame_->Push(r0); 3122 frame_->EmitPush(r0);
3123 } 3123 }
3124 } 3124 }
3125 3125
3126 3126
3127 void CodeGenerator::VisitThisFunction(ThisFunction* node) { 3127 void CodeGenerator::VisitThisFunction(ThisFunction* node) {
3128 __ ldr(r0, frame_->Function()); 3128 __ ldr(r0, frame_->Function());
3129 frame_->Push(r0); 3129 frame_->EmitPush(r0);
3130 } 3130 }
3131 3131
3132 3132
3133 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 3133 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
3134 Comment cmnt(masm_, "[ CompareOperation"); 3134 Comment cmnt(masm_, "[ CompareOperation");
3135 3135
3136 // Get the expressions from the node. 3136 // Get the expressions from the node.
3137 Expression* left = node->left(); 3137 Expression* left = node->left();
3138 Expression* right = node->right(); 3138 Expression* right = node->right();
3139 Token::Value op = node->op(); 3139 Token::Value op = node->op();
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
3293 Comparison(ge); 3293 Comparison(ge);
3294 break; 3294 break;
3295 3295
3296 case Token::EQ_STRICT: 3296 case Token::EQ_STRICT:
3297 Comparison(eq, true); 3297 Comparison(eq, true);
3298 break; 3298 break;
3299 3299
3300 case Token::IN: 3300 case Token::IN:
3301 __ mov(r0, Operand(1)); // not counting receiver 3301 __ mov(r0, Operand(1)); // not counting receiver
3302 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); 3302 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2);
3303 frame_->Push(r0); 3303 frame_->EmitPush(r0);
3304 break; 3304 break;
3305 3305
3306 case Token::INSTANCEOF: 3306 case Token::INSTANCEOF:
3307 __ mov(r0, Operand(1)); // not counting receiver 3307 __ mov(r0, Operand(1)); // not counting receiver
3308 frame_->InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS, 2); 3308 frame_->InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS, 2);
3309 __ tst(r0, Operand(r0)); 3309 __ tst(r0, Operand(r0));
3310 cc_reg_ = eq; 3310 cc_reg_ = eq;
3311 break; 3311 break;
3312 3312
3313 default: 3313 default:
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3381 __ mov(r2, Operand(name)); 3381 __ mov(r2, Operand(name));
3382 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3382 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3383 3383
3384 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3384 Variable* var = expression_->AsVariableProxy()->AsVariable();
3385 if (var != NULL) { 3385 if (var != NULL) {
3386 ASSERT(var->is_global()); 3386 ASSERT(var->is_global());
3387 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 3387 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
3388 } else { 3388 } else {
3389 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3389 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3390 } 3390 }
3391 frame->Push(r0); 3391 frame->EmitPush(r0);
3392 break; 3392 break;
3393 } 3393 }
3394 3394
3395 case KEYED: { 3395 case KEYED: {
3396 // TODO(1241834): Make sure that this it is safe to ignore the 3396 // TODO(1241834): Make sure that this it is safe to ignore the
3397 // distinction between expressions in a typeof and not in a typeof. 3397 // distinction between expressions in a typeof and not in a typeof.
3398 Comment cmnt(masm, "[ Load from keyed Property"); 3398 Comment cmnt(masm, "[ Load from keyed Property");
3399 ASSERT(property != NULL); 3399 ASSERT(property != NULL);
3400 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 3400 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3401 3401
3402 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3402 Variable* var = expression_->AsVariableProxy()->AsVariable();
3403 if (var != NULL) { 3403 if (var != NULL) {
3404 ASSERT(var->is_global()); 3404 ASSERT(var->is_global());
3405 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 3405 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
3406 } else { 3406 } else {
3407 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3407 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3408 } 3408 }
3409 frame->Push(r0); 3409 frame->EmitPush(r0);
3410 break; 3410 break;
3411 } 3411 }
3412 3412
3413 default: 3413 default:
3414 UNREACHABLE(); 3414 UNREACHABLE();
3415 } 3415 }
3416 } 3416 }
3417 3417
3418 3418
3419 void Reference::SetValue(InitState init_state) { 3419 void Reference::SetValue(InitState init_state) {
3420 ASSERT(!is_illegal()); 3420 ASSERT(!is_illegal());
3421 ASSERT(!cgen_->has_cc()); 3421 ASSERT(!cgen_->has_cc());
3422 MacroAssembler* masm = cgen_->masm(); 3422 MacroAssembler* masm = cgen_->masm();
3423 VirtualFrame* frame = cgen_->frame(); 3423 VirtualFrame* frame = cgen_->frame();
3424 Property* property = expression_->AsProperty(); 3424 Property* property = expression_->AsProperty();
3425 if (property != NULL) { 3425 if (property != NULL) {
3426 __ RecordPosition(property->position()); 3426 __ RecordPosition(property->position());
3427 } 3427 }
3428 3428
3429 switch (type_) { 3429 switch (type_) {
3430 case SLOT: { 3430 case SLOT: {
3431 Comment cmnt(masm, "[ Store to Slot"); 3431 Comment cmnt(masm, "[ Store to Slot");
3432 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3432 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3433 ASSERT(slot != NULL); 3433 ASSERT(slot != NULL);
3434 if (slot->type() == Slot::LOOKUP) { 3434 if (slot->type() == Slot::LOOKUP) {
3435 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 3435 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
3436 3436
3437 // For now, just do a runtime call. 3437 // For now, just do a runtime call.
3438 frame->Push(cp); 3438 frame->EmitPush(cp);
3439 __ mov(r0, Operand(slot->var()->name())); 3439 __ mov(r0, Operand(slot->var()->name()));
3440 frame->Push(r0); 3440 frame->EmitPush(r0);
3441 3441
3442 if (init_state == CONST_INIT) { 3442 if (init_state == CONST_INIT) {
3443 // Same as the case for a normal store, but ignores attribute 3443 // Same as the case for a normal store, but ignores attribute
3444 // (e.g. READ_ONLY) of context slot so that we can initialize 3444 // (e.g. READ_ONLY) of context slot so that we can initialize
3445 // const properties (introduced via eval("const foo = (some 3445 // const properties (introduced via eval("const foo = (some
3446 // expr);")). Also, uses the current function context instead of 3446 // expr);")). Also, uses the current function context instead of
3447 // the top context. 3447 // the top context.
3448 // 3448 //
3449 // Note that we must declare the foo upon entry of eval(), via a 3449 // Note that we must declare the foo upon entry of eval(), via a
3450 // context slot declaration, but we cannot initialize it at the 3450 // context slot declaration, but we cannot initialize it at the
3451 // same time, because the const declaration may be at the end of 3451 // same time, because the const declaration may be at the end of
3452 // the eval code (sigh...) and the const variable may have been 3452 // the eval code (sigh...) and the const variable may have been
3453 // used before (where its value is 'undefined'). Thus, we can only 3453 // used before (where its value is 'undefined'). Thus, we can only
3454 // do the initialization when we actually encounter the expression 3454 // do the initialization when we actually encounter the expression
3455 // and when the expression operands are defined and valid, and 3455 // and when the expression operands are defined and valid, and
3456 // thus we need the split into 2 operations: declaration of the 3456 // thus we need the split into 2 operations: declaration of the
3457 // context slot followed by initialization. 3457 // context slot followed by initialization.
3458 frame->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 3458 frame->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
3459 } else { 3459 } else {
3460 frame->CallRuntime(Runtime::kStoreContextSlot, 3); 3460 frame->CallRuntime(Runtime::kStoreContextSlot, 3);
3461 } 3461 }
3462 // Storing a variable must keep the (new) value on the expression 3462 // Storing a variable must keep the (new) value on the expression
3463 // stack. This is necessary for compiling assignment expressions. 3463 // stack. This is necessary for compiling assignment expressions.
3464 frame->Push(r0); 3464 frame->EmitPush(r0);
3465 3465
3466 } else { 3466 } else {
3467 ASSERT(slot->var()->mode() != Variable::DYNAMIC); 3467 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
3468 3468
3469 JumpTarget exit(cgen_); 3469 JumpTarget exit(cgen_);
3470 if (init_state == CONST_INIT) { 3470 if (init_state == CONST_INIT) {
3471 ASSERT(slot->var()->mode() == Variable::CONST); 3471 ASSERT(slot->var()->mode() == Variable::CONST);
3472 // Only the first const initialization must be executed (the slot 3472 // Only the first const initialization must be executed (the slot
3473 // still contains 'the hole' value). When the assignment is 3473 // still contains 'the hole' value). When the assignment is
3474 // executed, the code is identical to a normal store (see below). 3474 // executed, the code is identical to a normal store (see below).
3475 Comment cmnt(masm, "[ Init const"); 3475 Comment cmnt(masm, "[ Init const");
3476 __ ldr(r2, cgen_->SlotOperand(slot, r2)); 3476 __ ldr(r2, cgen_->SlotOperand(slot, r2));
3477 __ cmp(r2, Operand(Factory::the_hole_value())); 3477 __ cmp(r2, Operand(Factory::the_hole_value()));
3478 exit.Branch(ne); 3478 exit.Branch(ne);
3479 } 3479 }
3480 3480
3481 // We must execute the store. Storing a variable must keep the 3481 // We must execute the store. Storing a variable must keep the
3482 // (new) value on the stack. This is necessary for compiling 3482 // (new) value on the stack. This is necessary for compiling
3483 // assignment expressions. 3483 // assignment expressions.
3484 // 3484 //
3485 // Note: We will reach here even with slot->var()->mode() == 3485 // Note: We will reach here even with slot->var()->mode() ==
3486 // Variable::CONST because of const declarations which will 3486 // Variable::CONST because of const declarations which will
3487 // initialize consts to 'the hole' value and by doing so, end up 3487 // initialize consts to 'the hole' value and by doing so, end up
3488 // calling this code. r2 may be loaded with context; used below in 3488 // calling this code. r2 may be loaded with context; used below in
3489 // RecordWrite. 3489 // RecordWrite.
3490 frame->Pop(r0); 3490 frame->Pop(r0);
3491 __ str(r0, cgen_->SlotOperand(slot, r2)); 3491 __ str(r0, cgen_->SlotOperand(slot, r2));
3492 frame->Push(r0); 3492 frame->EmitPush(r0);
3493 if (slot->type() == Slot::CONTEXT) { 3493 if (slot->type() == Slot::CONTEXT) {
3494 // Skip write barrier if the written value is a smi. 3494 // Skip write barrier if the written value is a smi.
3495 __ tst(r0, Operand(kSmiTagMask)); 3495 __ tst(r0, Operand(kSmiTagMask));
3496 exit.Branch(eq); 3496 exit.Branch(eq);
3497 // r2 is loaded with context when calling SlotOperand above. 3497 // r2 is loaded with context when calling SlotOperand above.
3498 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 3498 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
3499 __ mov(r3, Operand(offset)); 3499 __ mov(r3, Operand(offset));
3500 __ RecordWrite(r2, r3, r1); 3500 __ RecordWrite(r2, r3, r1);
3501 } 3501 }
3502 // If we definitely did not jump over the assignment, we do not need 3502 // If we definitely did not jump over the assignment, we do not need
3503 // to bind the exit label. Doing so can defeat peephole 3503 // to bind the exit label. Doing so can defeat peephole
3504 // optimization. 3504 // optimization.
3505 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { 3505 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) {
3506 exit.Bind(); 3506 exit.Bind();
3507 } 3507 }
3508 } 3508 }
3509 break; 3509 break;
3510 } 3510 }
3511 3511
3512 case NAMED: { 3512 case NAMED: {
3513 Comment cmnt(masm, "[ Store to named Property"); 3513 Comment cmnt(masm, "[ Store to named Property");
3514 // Call the appropriate IC code. 3514 // Call the appropriate IC code.
3515 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3515 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3516 frame->Pop(r0); // value 3516 frame->Pop(r0); // value
3517 // Setup the name register. 3517 // Setup the name register.
3518 Handle<String> name(GetName()); 3518 Handle<String> name(GetName());
3519 __ mov(r2, Operand(name)); 3519 __ mov(r2, Operand(name));
3520 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3520 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3521 frame->Push(r0); 3521 frame->EmitPush(r0);
3522 break; 3522 break;
3523 } 3523 }
3524 3524
3525 case KEYED: { 3525 case KEYED: {
3526 Comment cmnt(masm, "[ Store to keyed Property"); 3526 Comment cmnt(masm, "[ Store to keyed Property");
3527 Property* property = expression_->AsProperty(); 3527 Property* property = expression_->AsProperty();
3528 ASSERT(property != NULL); 3528 ASSERT(property != NULL);
3529 __ RecordPosition(property->position()); 3529 __ RecordPosition(property->position());
3530 3530
3531 // Call IC code. 3531 // Call IC code.
3532 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3532 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3533 // TODO(1222589): Make the IC grab the values from the stack. 3533 // TODO(1222589): Make the IC grab the values from the stack.
3534 frame->Pop(r0); // value 3534 frame->Pop(r0); // value
3535 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3535 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
3536 frame->Push(r0); 3536 frame->EmitPush(r0);
3537 break; 3537 break;
3538 } 3538 }
3539 3539
3540 default: 3540 default:
3541 UNREACHABLE(); 3541 UNREACHABLE();
3542 } 3542 }
3543 } 3543 }
3544 3544
3545 3545
3546 void GetPropertyStub::Generate(MacroAssembler* masm) { 3546 void GetPropertyStub::Generate(MacroAssembler* masm) {
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after
4445 __ mov(r2, Operand(0)); 4445 __ mov(r2, Operand(0));
4446 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 4446 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
4447 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), 4447 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
4448 RelocInfo::CODE_TARGET); 4448 RelocInfo::CODE_TARGET);
4449 } 4449 }
4450 4450
4451 4451
4452 #undef __ 4452 #undef __
4453 4453
4454 } } // namespace v8::internal 4454 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | v8/src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698