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

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

Issue 6262: Improve performance of arguments object allocation by taking... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen.h ('k') | src/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/codegen.h ('k') | src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698