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

Side by Side Diff: src/codegen-ia32.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
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 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 break_stack_height_(0) { 511 break_stack_height_(0) {
512 } 512 }
513 513
514 514
515 // Calling conventions: 515 // Calling conventions:
516 // ebp: frame pointer 516 // ebp: frame pointer
517 // esp: stack pointer 517 // esp: stack pointer
518 // edi: caller's parameter pointer 518 // edi: caller's parameter pointer
519 // esi: callee's context 519 // esi: callee's context
520 520
521
522 void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) { 521 void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) {
523 // Record the position for debugging purposes. 522 // Record the position for debugging purposes.
524 __ RecordPosition(fun->start_position()); 523 __ RecordPosition(fun->start_position());
525 524
526 Scope* scope = fun->scope(); 525 Scope* scope = fun->scope();
527 ZoneList<Statement*>* body = fun->body(); 526 ZoneList<Statement*>* body = fun->body();
528 527
529 // Initialize state. 528 // Initialize state.
530 { CodeGenState state(this); 529 { CodeGenState state(this);
531 scope_ = scope; 530 scope_ = scope;
(...skipping 26 matching lines...) Expand all
558 // when the push has happened. 557 // when the push has happened.
559 bool arguments_object_allocated = false; 558 bool arguments_object_allocated = false;
560 bool arguments_object_saved = false; 559 bool arguments_object_saved = false;
561 560
562 // Allocate arguments object. 561 // Allocate arguments object.
563 // The arguments object pointer needs to be saved in ecx, since we need 562 // The arguments object pointer needs to be saved in ecx, since we need
564 // to store arguments into the context. 563 // to store arguments into the context.
565 if (scope->arguments() != NULL) { 564 if (scope->arguments() != NULL) {
566 ASSERT(scope->arguments_shadow() != NULL); 565 ASSERT(scope->arguments_shadow() != NULL);
567 Comment cmnt(masm_, "[ allocate arguments object"); 566 Comment cmnt(masm_, "[ allocate arguments object");
567 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
568 __ lea(eax, ReceiverOperand());
568 __ push(FunctionOperand()); 569 __ push(FunctionOperand());
569 __ CallRuntime(Runtime::kNewArguments, 1); 570 __ push(eax);
571 __ push(Immediate(Smi::FromInt(scope->num_parameters())));
572 __ CallStub(&stub);
570 __ mov(ecx, Operand(eax)); 573 __ mov(ecx, Operand(eax));
571 arguments_object_allocated = true; 574 arguments_object_allocated = true;
572 } 575 }
573 576
574 // Allocate space for locals and initialize them. 577 // Allocate space for locals and initialize them.
575 if (scope->num_stack_slots() > 0) { 578 if (scope->num_stack_slots() > 0) {
576 Comment cmnt(masm_, "[ allocate space for locals"); 579 Comment cmnt(masm_, "[ allocate space for locals");
577 __ Set(eax, Immediate(Factory::undefined_value())); 580 __ Set(eax, Immediate(Factory::undefined_value()));
578 for (int i = scope->num_stack_slots(); i-- > 0; ) __ push(eax); 581 for (int i = scope->num_stack_slots(); i-- > 0; ) __ push(eax);
579 } 582 }
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; 1064 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND";
1062 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; 1065 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR";
1063 case Token::SAR: return "GenericBinaryOpStub_SAR"; 1066 case Token::SAR: return "GenericBinaryOpStub_SAR";
1064 case Token::SHL: return "GenericBinaryOpStub_SHL"; 1067 case Token::SHL: return "GenericBinaryOpStub_SHL";
1065 case Token::SHR: return "GenericBinaryOpStub_SHR"; 1068 case Token::SHR: return "GenericBinaryOpStub_SHR";
1066 default: return "GenericBinaryOpStub"; 1069 default: return "GenericBinaryOpStub";
1067 } 1070 }
1068 } 1071 }
1069 1072
1070 1073
1071 class ArgumentsAccessStub: public CodeStub {
1072 public:
1073 explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { }
1074
1075 private:
1076 bool is_length_;
1077
1078 Major MajorKey() { return ArgumentsAccess; }
1079 int MinorKey() { return is_length_ ? 1 : 0; }
1080 void Generate(MacroAssembler* masm);
1081
1082 const char* GetName() { return "ArgumentsAccessStub"; }
1083
1084 #ifdef DEBUG
1085 void Print() {
1086 PrintF("ArgumentsAccessStub (is_length %s)\n",
1087 is_length_ ? "true" : "false");
1088 }
1089 #endif
1090 };
1091
1092
1093 void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op, 1074 void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op,
1094 OverwriteMode overwrite_mode) { 1075 OverwriteMode overwrite_mode) {
1095 Comment cmnt(masm_, "[ BinaryOperation"); 1076 Comment cmnt(masm_, "[ BinaryOperation");
1096 Comment cmnt_token(masm_, Token::String(op)); 1077 Comment cmnt_token(masm_, Token::String(op));
1097 switch (op) { 1078 switch (op) {
1098 case Token::ADD: 1079 case Token::ADD:
1099 case Token::SUB: 1080 case Token::SUB:
1100 case Token::MUL: 1081 case Token::MUL:
1101 case Token::DIV: 1082 case Token::DIV:
1102 case Token::MOD: { 1083 case Token::MOD: {
(...skipping 2203 matching lines...) Expand 10 before | Expand all | Expand 10 after
3306 3287
3307 void Ia32CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 3288 void Ia32CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
3308 ASSERT(args->length() == 0); 3289 ASSERT(args->length() == 0);
3309 3290
3310 // Seed the result with the formal parameters count, which will be 3291 // Seed the result with the formal parameters count, which will be
3311 // used in case no arguments adaptor frame is found below the 3292 // used in case no arguments adaptor frame is found below the
3312 // current frame. 3293 // current frame.
3313 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 3294 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
3314 3295
3315 // Call the shared stub to get to the arguments.length. 3296 // Call the shared stub to get to the arguments.length.
3316 ArgumentsAccessStub stub(true); 3297 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
3317 __ CallStub(&stub); 3298 __ CallStub(&stub);
3318 __ push(eax); 3299 __ push(eax);
3319 } 3300 }
3320 3301
3321 3302
3322 void Ia32CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3303 void Ia32CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3323 ASSERT(args->length() == 1); 3304 ASSERT(args->length() == 1);
3324 Label leave; 3305 Label leave;
3325 Load(args->at(0)); // Load the object. 3306 Load(args->at(0)); // Load the object.
3326 __ mov(eax, TOS); 3307 __ mov(eax, TOS);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3369 3350
3370 void Ia32CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 3351 void Ia32CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
3371 ASSERT(args->length() == 1); 3352 ASSERT(args->length() == 1);
3372 3353
3373 // Load the key onto the stack and set register eax to the formal 3354 // Load the key onto the stack and set register eax to the formal
3374 // parameters count for the currently executing function. 3355 // parameters count for the currently executing function.
3375 Load(args->at(0)); 3356 Load(args->at(0));
3376 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 3357 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
3377 3358
3378 // Call the shared stub to get to arguments[key]. 3359 // Call the shared stub to get to arguments[key].
3379 ArgumentsAccessStub stub(false); 3360 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
3380 __ CallStub(&stub); 3361 __ CallStub(&stub);
3381 __ mov(TOS, eax); 3362 __ mov(TOS, eax);
3382 } 3363 }
3383 3364
3384 3365
3385 void Ia32CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 3366 void Ia32CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
3386 ASSERT(args->length() == 2); 3367 ASSERT(args->length() == 2);
3387 3368
3388 // Load the two objects into registers and perform the comparison. 3369 // Load the two objects into registers and perform the comparison.
3389 Load(args->at(0)); 3370 Load(args->at(0));
(...skipping 1418 matching lines...) Expand 10 before | Expand all | Expand 10 after
4808 __ fchs(); 4789 __ fchs();
4809 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 4790 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
4810 4791
4811 __ bind(&done); 4792 __ bind(&done);
4812 4793
4813 __ StubReturn(1); 4794 __ StubReturn(1);
4814 } 4795 }
4815 4796
4816 4797
4817 void ArgumentsAccessStub::Generate(MacroAssembler* masm) { 4798 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
4818 // Check that the key is a smi for non-length access. 4799 // If we're reading an element we need to check that the key is a smi.
4819 Label slow; 4800 Label slow;
4820 if (!is_length_) { 4801 if (type_ == READ_ELEMENT) {
4821 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // skip return address 4802 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // skip return address
4822 __ test(ebx, Immediate(kSmiTagMask)); 4803 __ test(ebx, Immediate(kSmiTagMask));
4823 __ j(not_zero, &slow, not_taken); 4804 __ j(not_zero, &slow, not_taken);
4824 } 4805 }
4825 4806
4826 // Check if the calling frame is an arguments adaptor frame. 4807 // Check if the calling frame is an arguments adaptor frame.
4827 Label adaptor; 4808 Label adaptor;
4828 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 4809 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
4829 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); 4810 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
4830 __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL); 4811 __ cmp(ecx, ArgumentsAdaptorFrame::SENTINEL);
4831 __ j(equal, &adaptor); 4812 if (type_ == NEW_OBJECT) {
4813 __ j(not_equal, &slow);
4814 } else {
4815 __ j(equal, &adaptor);
4816 }
4832 4817
4833 // The displacement is used for skipping the return address on the 4818 // The displacement is used for skipping the return address on the
4834 // stack. It is the offset of the last parameter (if any) relative 4819 // stack. It is the offset of the last parameter (if any) relative
4835 // to the frame pointer. 4820 // to the frame pointer.
4836 static const int kDisplacement = 1 * kPointerSize; 4821 static const int kDisplacement = 1 * kPointerSize;
4837 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this 4822 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); // shifting code depends on this
4838 4823
4839 if (is_length_) { 4824 if (type_ == READ_LENGTH) {
4840 // Do nothing. The length is already in register eax. 4825 // Nothing to do: The formal number of parameters has already been
4841 } else { 4826 // passed in register eax by calling function. Just return it.
4827 __ ret(0);
4828 } else if (type_ == READ_ELEMENT) {
4842 // Check index against formal parameters count limit passed in 4829 // Check index against formal parameters count limit passed in
4843 // through register eax. Use unsigned comparison to get negative 4830 // through register eax. Use unsigned comparison to get negative
4844 // check for free. 4831 // check for free.
4845 __ cmp(ebx, Operand(eax)); 4832 __ cmp(ebx, Operand(eax));
4846 __ j(above_equal, &slow, not_taken); 4833 __ j(above_equal, &slow, not_taken);
4847 4834
4848 // Read the argument from the stack. 4835 // Read the argument from the stack and return it.
4849 __ lea(edx, Operand(ebp, eax, times_2, 0)); 4836 __ lea(edx, Operand(ebp, eax, times_2, 0));
4850 __ neg(ebx); 4837 __ neg(ebx);
4851 __ mov(eax, Operand(edx, ebx, times_2, kDisplacement)); 4838 __ mov(eax, Operand(edx, ebx, times_2, kDisplacement));
4839 __ ret(0);
4840 } else {
4841 ASSERT(type_ == NEW_OBJECT);
4842 // Do nothing here.
4852 } 4843 }
4853 4844
4854 // Return the length or the argument.
4855 __ ret(0);
4856
4857 // Arguments adaptor case: Find the length or the actual argument in 4845 // Arguments adaptor case: Find the length or the actual argument in
4858 // the calling frame. 4846 // the calling frame.
4859 __ bind(&adaptor); 4847 __ bind(&adaptor);
4860 if (is_length_) { 4848 if (type_ == READ_LENGTH) {
4861 // Read the arguments length from the adaptor frame. 4849 // Read the arguments length from the adaptor frame and return it.
4862 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4850 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
4863 } else { 4851 __ ret(0);
4852 } else if (type_ == READ_ELEMENT) {
4864 // Check index against actual arguments limit found in the 4853 // Check index against actual arguments limit found in the
4865 // arguments adaptor frame. Use unsigned comparison to get 4854 // arguments adaptor frame. Use unsigned comparison to get
4866 // negative check for free. 4855 // negative check for free.
4867 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4856 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
4868 __ cmp(ebx, Operand(ecx)); 4857 __ cmp(ebx, Operand(ecx));
4869 __ j(above_equal, &slow, not_taken); 4858 __ j(above_equal, &slow, not_taken);
4870 4859
4871 // Read the argument from the stack. 4860 // Read the argument from the stack and return it.
4872 __ lea(edx, Operand(edx, ecx, times_2, 0)); 4861 __ lea(edx, Operand(edx, ecx, times_2, 0));
4873 __ neg(ebx); 4862 __ neg(ebx);
4874 __ mov(eax, Operand(edx, ebx, times_2, kDisplacement)); 4863 __ mov(eax, Operand(edx, ebx, times_2, kDisplacement));
4864 __ ret(0);
4865 } else {
4866 ASSERT(type_ == NEW_OBJECT);
4867 // Patch the arguments.length and the parameters pointer.
4868 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
4869 __ mov(Operand(esp, 1 * kPointerSize), ecx);
4870 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement + 1 * kPointerSize));
4871 __ mov(Operand(esp, 2 * kPointerSize), edx);
4872 __ bind(&slow);
4873 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3);
4875 } 4874 }
4876 4875
4877 // Return the length or the argument.
4878 __ ret(0);
4879
4880 // Slow-case: Handle non-smi or out-of-bounds access to arguments 4876 // Slow-case: Handle non-smi or out-of-bounds access to arguments
4881 // by calling the runtime system. 4877 // by calling the runtime system.
4882 if (!is_length_) { 4878 if (type_ == READ_ELEMENT) {
4883 __ bind(&slow); 4879 __ bind(&slow);
4884 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); 4880 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
4885 } 4881 }
4886 } 4882 }
4887 4883
4888 4884
4889 void CompareStub::Generate(MacroAssembler* masm) { 4885 void CompareStub::Generate(MacroAssembler* masm) {
4890 Label call_builtin, done; 4886 Label call_builtin, done;
4891 // Save the return address (and get it off the stack). 4887 // Save the return address (and get it off the stack).
4892 __ pop(ecx); 4888 __ pop(ecx);
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
5341 bool is_eval) { 5337 bool is_eval) {
5342 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); 5338 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval);
5343 if (!code.is_null()) { 5339 if (!code.is_null()) {
5344 Counters::total_compiled_code_size.Increment(code->instruction_size()); 5340 Counters::total_compiled_code_size.Increment(code->instruction_size());
5345 } 5341 }
5346 return code; 5342 return code;
5347 } 5343 }
5348 5344
5349 5345
5350 } } // namespace v8::internal 5346 } } // namespace v8::internal
OLDNEW
« src/codegen-arm.cc ('K') | « src/codegen-arm.cc ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698