| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |