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 |