Chromium Code Reviews| 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 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 580 } | 580 } |
| 581 | 581 |
| 582 // Store the arguments object. | 582 // Store the arguments object. |
| 583 // This must happen after context initialization because | 583 // This must happen after context initialization because |
| 584 // the arguments array may be stored in the context! | 584 // the arguments array may be stored in the context! |
| 585 if (scope->arguments() != NULL) { | 585 if (scope->arguments() != NULL) { |
| 586 ASSERT(scope->arguments_shadow() != NULL); | 586 ASSERT(scope->arguments_shadow() != NULL); |
| 587 Comment cmnt(masm_, "[ allocate arguments object"); | 587 Comment cmnt(masm_, "[ allocate arguments object"); |
| 588 { Reference shadow_ref(this, scope->arguments_shadow()); | 588 { Reference shadow_ref(this, scope->arguments_shadow()); |
| 589 { Reference arguments_ref(this, scope->arguments()); | 589 { Reference arguments_ref(this, scope->arguments()); |
| 590 __ ldr(r0, FunctionOperand()); | 590 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
| 591 __ push(r0); | 591 __ ldr(r2, FunctionOperand()); |
| 592 __ CallRuntime(Runtime::kNewArguments, 1); | 592 __ add(r1, fp, Operand((2 + scope->num_parameters()) * kPointerSize)); |
|
Mads Ager (chromium)
2008/10/06 06:05:59
Could you add a comment to say what the constant 2
| |
| 593 __ mov(r0, Operand(Smi::FromInt(scope->num_parameters()))); | |
| 594 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); | |
| 595 __ CallStub(&stub); | |
| 593 __ push(r0); | 596 __ push(r0); |
| 594 SetValue(&arguments_ref); | 597 SetValue(&arguments_ref); |
| 595 } | 598 } |
| 596 SetValue(&shadow_ref); | 599 SetValue(&shadow_ref); |
| 597 } | 600 } |
| 598 __ pop(r0); // Value is no longer needed. | 601 __ pop(r0); // Value is no longer needed. |
| 599 } | 602 } |
| 600 | 603 |
| 601 // Generate code to 'execute' declarations and initialize | 604 // Generate code to 'execute' declarations and initialize |
| 602 // functions (source elements). In case of an illegal | 605 // functions (source elements). In case of an illegal |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 956 #ifdef DEBUG | 959 #ifdef DEBUG |
| 957 void Print() { | 960 void Print() { |
| 958 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n", | 961 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n", |
| 959 static_cast<int>(kind_), | 962 static_cast<int>(kind_), |
| 960 argc_); | 963 argc_); |
| 961 } | 964 } |
| 962 #endif | 965 #endif |
| 963 }; | 966 }; |
| 964 | 967 |
| 965 | 968 |
| 966 class ArgumentsAccessStub: public CodeStub { | |
| 967 public: | |
| 968 explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { } | |
| 969 | |
| 970 private: | |
| 971 bool is_length_; | |
| 972 | |
| 973 Major MajorKey() { return ArgumentsAccess; } | |
| 974 int MinorKey() { return is_length_ ? 1 : 0; } | |
| 975 void Generate(MacroAssembler* masm); | |
| 976 | |
| 977 const char* GetName() { return "ArgumentsAccessStub"; } | |
| 978 | |
| 979 #ifdef DEBUG | |
| 980 void Print() { | |
| 981 PrintF("ArgumentsAccessStub (is_length %s)\n", | |
| 982 is_length_ ? "true" : "false"); | |
| 983 } | |
| 984 #endif | |
| 985 }; | |
| 986 | |
| 987 | |
| 988 void ArmCodeGenerator::GetReferenceProperty(Expression* key) { | 969 void ArmCodeGenerator::GetReferenceProperty(Expression* key) { |
| 989 ASSERT(!ref()->is_illegal()); | 970 ASSERT(!ref()->is_illegal()); |
| 990 Reference::Type type = ref()->type(); | 971 Reference::Type type = ref()->type(); |
| 991 | 972 |
| 992 // TODO(1241834): Make sure that this it is safe to ignore the distinction | 973 // TODO(1241834): Make sure that this it is safe to ignore the distinction |
| 993 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance | 974 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance |
| 994 // that reference errors can be thrown below, we must distinguish between | 975 // that reference errors can be thrown below, we must distinguish between |
| 995 // the two kinds of loads (typeof expression loads must not throw a | 976 // the two kinds of loads (typeof expression loads must not throw a |
| 996 // reference error). | 977 // reference error). |
| 997 if (type == Reference::NAMED) { | 978 if (type == Reference::NAMED) { |
| (...skipping 1852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2850 | 2831 |
| 2851 | 2832 |
| 2852 void ArmCodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 2833 void ArmCodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
| 2853 ASSERT(args->length() == 0); | 2834 ASSERT(args->length() == 0); |
| 2854 | 2835 |
| 2855 // Seed the result with the formal parameters count, which will be used | 2836 // Seed the result with the formal parameters count, which will be used |
| 2856 // in case no arguments adaptor frame is found below the current frame. | 2837 // in case no arguments adaptor frame is found below the current frame. |
| 2857 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); | 2838 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); |
| 2858 | 2839 |
| 2859 // Call the shared stub to get to the arguments.length. | 2840 // Call the shared stub to get to the arguments.length. |
| 2860 ArgumentsAccessStub stub(true); | 2841 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); |
| 2861 __ CallStub(&stub); | 2842 __ CallStub(&stub); |
| 2862 __ push(r0); | 2843 __ push(r0); |
| 2863 } | 2844 } |
| 2864 | 2845 |
| 2865 | 2846 |
| 2866 void ArmCodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 2847 void ArmCodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { |
| 2867 ASSERT(args->length() == 1); | 2848 ASSERT(args->length() == 1); |
| 2868 | 2849 |
| 2869 // Satisfy contract with ArgumentsAccessStub: | 2850 // Satisfy contract with ArgumentsAccessStub: |
| 2870 // Load the key into r1 and the formal parameters count into r0. | 2851 // Load the key into r1 and the formal parameters count into r0. |
| 2871 Load(args->at(0)); | 2852 Load(args->at(0)); |
| 2872 __ pop(r1); | 2853 __ pop(r1); |
| 2873 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); | 2854 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); |
| 2874 | 2855 |
| 2875 // Call the shared stub to get to arguments[key]. | 2856 // Call the shared stub to get to arguments[key]. |
| 2876 ArgumentsAccessStub stub(false); | 2857 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
| 2877 __ CallStub(&stub); | 2858 __ CallStub(&stub); |
| 2878 __ push(r0); | 2859 __ push(r0); |
| 2879 } | 2860 } |
| 2880 | 2861 |
| 2881 | 2862 |
| 2882 void ArmCodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 2863 void ArmCodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| 2883 ASSERT(args->length() == 2); | 2864 ASSERT(args->length() == 2); |
| 2884 | 2865 |
| 2885 // Load the two objects into registers and perform the comparison. | 2866 // Load the two objects into registers and perform the comparison. |
| 2886 Load(args->at(0)); | 2867 Load(args->at(0)); |
| (...skipping 1532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4419 } | 4400 } |
| 4420 | 4401 |
| 4421 | 4402 |
| 4422 void ArgumentsAccessStub::Generate(MacroAssembler* masm) { | 4403 void ArgumentsAccessStub::Generate(MacroAssembler* masm) { |
| 4423 // ----------- S t a t e ------------- | 4404 // ----------- S t a t e ------------- |
| 4424 // -- r0: formal number of parameters for the calling function | 4405 // -- r0: formal number of parameters for the calling function |
| 4425 // -- r1: key (if value access) | 4406 // -- r1: key (if value access) |
| 4426 // -- lr: return address | 4407 // -- lr: return address |
| 4427 // ----------------------------------- | 4408 // ----------------------------------- |
| 4428 | 4409 |
| 4429 // Check that the key is a smi for non-length accesses. | 4410 // If we're reading an element we need to check that the key is a smi. |
| 4430 Label slow; | 4411 Label slow; |
| 4431 if (!is_length_) { | 4412 if (type_ == READ_ELEMENT) { |
| 4432 __ tst(r1, Operand(kSmiTagMask)); | 4413 __ tst(r1, Operand(kSmiTagMask)); |
| 4433 __ b(ne, &slow); | 4414 __ b(ne, &slow); |
| 4434 } | 4415 } |
| 4435 | 4416 |
| 4436 // Check if the calling frame is an arguments adaptor frame. | 4417 // Check if the calling frame is an arguments adaptor frame. |
| 4437 // r0: formal number of parameters | 4418 // r0: formal number of parameters |
| 4438 // r1: key (if access) | 4419 // r1: key (if access) |
| 4439 Label adaptor; | 4420 Label adaptor; |
| 4440 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 4421 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 4441 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 4422 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
| 4442 __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL)); | 4423 __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL)); |
| 4443 __ b(eq, &adaptor); | 4424 if (type_ == NEW_OBJECT) { |
| 4425 __ b(ne, &slow); | |
| 4426 } else { | |
| 4427 __ b(eq, &adaptor); | |
| 4428 } | |
| 4444 | 4429 |
| 4445 static const int kParamDisplacement = | 4430 static const int kParamDisplacement = |
| 4446 StandardFrameConstants::kCallerSPOffset - kPointerSize; | 4431 StandardFrameConstants::kCallerSPOffset - kPointerSize; |
| 4447 | 4432 |
| 4448 if (is_length_) { | 4433 if (type_ == READ_LENGTH) { |
| 4449 // Nothing to do: the formal length of parameters has been passed in r0 | 4434 // Nothing to do: The formal number of parameters has already been |
| 4450 // by the calling function. | 4435 // passed in register r0 by calling function. Just return it. |
| 4451 } else { | 4436 __ mov(pc, lr); |
| 4437 } else if (type_ == READ_ELEMENT) { | |
| 4452 // Check index against formal parameter count. Use unsigned comparison to | 4438 // Check index against formal parameter count. Use unsigned comparison to |
| 4453 // get the negative check for free. | 4439 // get the negative check for free. |
| 4454 // r0: formal number of parameters | 4440 // r0: formal number of parameters |
| 4455 // r1: index | 4441 // r1: index |
| 4456 __ cmp(r1, r0); | 4442 __ cmp(r1, r0); |
| 4457 __ b(cs, &slow); | 4443 __ b(cs, &slow); |
| 4458 | 4444 |
| 4459 // Read the argument from the current frame. | 4445 // Read the argument from the current frame and return it. |
| 4460 __ sub(r3, r0, r1); | 4446 __ sub(r3, r0, r1); |
| 4461 __ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); | 4447 __ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4462 __ ldr(r0, MemOperand(r3, kParamDisplacement)); | 4448 __ ldr(r0, MemOperand(r3, kParamDisplacement)); |
| 4449 __ mov(pc, lr); | |
| 4450 } else { | |
| 4451 ASSERT(type_ == NEW_OBJECT); | |
| 4452 // Do nothing here. | |
| 4463 } | 4453 } |
| 4464 | 4454 |
| 4465 // Return to the calling function. | |
| 4466 __ mov(pc, lr); | |
| 4467 | |
| 4468 // An arguments adaptor frame is present. Find the length or the actual | 4455 // An arguments adaptor frame is present. Find the length or the actual |
| 4469 // argument in the calling frame. | 4456 // argument in the calling frame. |
| 4470 // r0: formal number of parameters | 4457 // r0: formal number of parameters |
| 4471 // r1: key | 4458 // r1: key |
| 4472 // r2: adaptor frame pointer | 4459 // r2: adaptor frame pointer |
| 4473 __ bind(&adaptor); | 4460 __ bind(&adaptor); |
| 4474 // Read the arguments length from the adaptor frame. This is the result if | 4461 // Read the arguments length from the adaptor frame. This is the result if |
| 4475 // only accessing the length, otherwise it is used in accessing the value | 4462 // only accessing the length, otherwise it is used in accessing the value |
| 4476 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 4463 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 4477 | 4464 |
| 4478 if (!is_length_) { | 4465 if (type_ == READ_LENGTH) { |
| 4466 // Return the length in r0. | |
| 4467 __ mov(pc, lr); | |
| 4468 } else if (type_ == READ_ELEMENT) { | |
| 4479 // Check index against actual arguments count. Use unsigned comparison to | 4469 // Check index against actual arguments count. Use unsigned comparison to |
| 4480 // get the negative check for free. | 4470 // get the negative check for free. |
| 4481 // r0: actual number of parameter | 4471 // r0: actual number of parameter |
| 4482 // r1: index | 4472 // r1: index |
| 4483 // r2: adaptor frame point | 4473 // r2: adaptor frame point |
| 4484 __ cmp(r1, r0); | 4474 __ cmp(r1, r0); |
| 4485 __ b(cs, &slow); | 4475 __ b(cs, &slow); |
| 4486 | 4476 |
| 4487 // Read the argument from the adaptor frame. | 4477 // Read the argument from the adaptor frame and return it. |
| 4488 __ sub(r3, r0, r1); | 4478 __ sub(r3, r0, r1); |
| 4489 __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); | 4479 __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4490 __ ldr(r0, MemOperand(r3, kParamDisplacement)); | 4480 __ ldr(r0, MemOperand(r3, kParamDisplacement)); |
| 4481 __ mov(pc, lr); | |
| 4482 } else { | |
| 4483 ASSERT(type_ == NEW_OBJECT); | |
| 4484 // Patch the arguments.length and the parameters pointer. | |
| 4485 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | |
| 4486 __ add(r3, r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | |
| 4487 __ add(r3, r3, Operand(kParamDisplacement + 1 * kPointerSize)); | |
| 4488 __ str(r3, MemOperand(sp, 1 * kPointerSize)); | |
| 4489 __ bind(&slow); | |
| 4490 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); | |
| 4491 } | 4491 } |
| 4492 | 4492 |
| 4493 // Return to the calling function. | 4493 // Return to the calling function. |
| 4494 __ mov(pc, lr); | 4494 if (type_ == READ_ELEMENT) { |
| 4495 | |
| 4496 if (!is_length_) { | |
| 4497 __ bind(&slow); | 4495 __ bind(&slow); |
| 4498 __ push(r1); | 4496 __ push(r1); |
| 4499 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); | 4497 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); |
| 4500 } | 4498 } |
| 4501 } | 4499 } |
| 4502 | 4500 |
| 4503 | 4501 |
| 4504 void ArmCodeGenerator::SetReferenceProperty(CodeGenerator* cgen, | 4502 void ArmCodeGenerator::SetReferenceProperty(CodeGenerator* cgen, |
| 4505 Reference* ref, | 4503 Reference* ref, |
| 4506 Expression* key) { | 4504 Expression* key) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4572 bool is_eval) { | 4570 bool is_eval) { |
| 4573 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); | 4571 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); |
| 4574 if (!code.is_null()) { | 4572 if (!code.is_null()) { |
| 4575 Counters::total_compiled_code_size.Increment(code->instruction_size()); | 4573 Counters::total_compiled_code_size.Increment(code->instruction_size()); |
| 4576 } | 4574 } |
| 4577 return code; | 4575 return code; |
| 4578 } | 4576 } |
| 4579 | 4577 |
| 4580 | 4578 |
| 4581 } } // namespace v8::internal | 4579 } } // namespace v8::internal |
| OLD | NEW |