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

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

Issue 507036: Use one runtime call for creating object/array literals in... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years 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/ast.h ('k') | src/ia32/fast-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-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 4251 matching lines...) Expand 10 before | Expand all | Expand 10 after
4262 __ cmp(boilerplate.reg(), Factory::undefined_value()); 4262 __ cmp(boilerplate.reg(), Factory::undefined_value());
4263 deferred->Branch(equal); 4263 deferred->Branch(equal);
4264 deferred->BindExit(); 4264 deferred->BindExit();
4265 literals.Unuse(); 4265 literals.Unuse();
4266 4266
4267 // Push the boilerplate object. 4267 // Push the boilerplate object.
4268 frame_->Push(&boilerplate); 4268 frame_->Push(&boilerplate);
4269 } 4269 }
4270 4270
4271 4271
4272 // Materialize the object literal 'node' in the literals array
4273 // 'literals' of the function. Leave the object boilerplate in
4274 // 'boilerplate'.
4275 class DeferredObjectLiteral: public DeferredCode {
4276 public:
4277 DeferredObjectLiteral(Register boilerplate,
4278 Register literals,
4279 ObjectLiteral* node)
4280 : boilerplate_(boilerplate), literals_(literals), node_(node) {
4281 set_comment("[ DeferredObjectLiteral");
4282 }
4283
4284 void Generate();
4285
4286 private:
4287 Register boilerplate_;
4288 Register literals_;
4289 ObjectLiteral* node_;
4290 };
4291
4292
4293 void DeferredObjectLiteral::Generate() {
4294 // Since the entry is undefined we call the runtime system to
4295 // compute the literal.
4296 // Literal array (0).
4297 __ push(literals_);
4298 // Literal index (1).
4299 __ push(Immediate(Smi::FromInt(node_->literal_index())));
4300 // Constant properties (2).
4301 __ push(Immediate(node_->constant_properties()));
4302 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
4303 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax);
4304 }
4305
4306
4307 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 4272 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
4308 Comment cmnt(masm_, "[ ObjectLiteral"); 4273 Comment cmnt(masm_, "[ ObjectLiteral");
4309 4274
4310 // Retrieve the literals array and check the allocated entry. Begin 4275 // Load a writable copy of the function of this activation in a
4311 // with a writable copy of the function of this activation in a
4312 // register. 4276 // register.
4313 frame_->PushFunction(); 4277 frame_->PushFunction();
4314 Result literals = frame_->Pop(); 4278 Result literals = frame_->Pop();
4315 literals.ToRegister(); 4279 literals.ToRegister();
4316 frame_->Spill(literals.reg()); 4280 frame_->Spill(literals.reg());
4317 4281
4318 // Load the literals array of the function. 4282 // Load the literals array of the function.
4319 __ mov(literals.reg(), 4283 __ mov(literals.reg(),
4320 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); 4284 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
4321 4285 // Literal array.
4322 // Load the literal at the ast saved index. 4286 frame_->Push(&literals);
4323 Result boilerplate = allocator_->Allocate(); 4287 // Literal index.
4324 ASSERT(boilerplate.is_valid()); 4288 frame_->Push(Smi::FromInt(node->literal_index()));
4325 int literal_offset = 4289 // Constant properties.
4326 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 4290 frame_->Push(node->constant_properties());
4327 __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset)); 4291 Result clone;
4328 4292 if (node->depth() > 1) {
4329 // Check whether we need to materialize the object literal boilerplate. 4293 clone = frame_->CallRuntime(Runtime::kCreateObjectLiteral, 3);
4330 // If so, jump to the deferred code passing the literals array. 4294 } else {
4331 DeferredObjectLiteral* deferred = 4295 clone = frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
4332 new DeferredObjectLiteral(boilerplate.reg(), literals.reg(), node);
4333 __ cmp(boilerplate.reg(), Factory::undefined_value());
4334 deferred->Branch(equal);
4335 deferred->BindExit();
4336 literals.Unuse();
4337
4338 // Push the boilerplate object.
4339 frame_->Push(&boilerplate);
4340 // Clone the boilerplate object.
4341 Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
4342 if (node->depth() == 1) {
4343 clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
4344 } 4296 }
4345 Result clone = frame_->CallRuntime(clone_function_id, 1);
4346 // Push the newly cloned literal object as the result.
4347 frame_->Push(&clone); 4297 frame_->Push(&clone);
4348 4298
4349 for (int i = 0; i < node->properties()->length(); i++) { 4299 for (int i = 0; i < node->properties()->length(); i++) {
4350 ObjectLiteral::Property* property = node->properties()->at(i); 4300 ObjectLiteral::Property* property = node->properties()->at(i);
4351 switch (property->kind()) { 4301 switch (property->kind()) {
4352 case ObjectLiteral::Property::CONSTANT: 4302 case ObjectLiteral::Property::CONSTANT:
4353 break; 4303 break;
4354 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 4304 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
4355 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; 4305 if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
4356 // else fall through. 4306 // else fall through.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4396 Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4); 4346 Result ignored = frame_->CallRuntime(Runtime::kDefineAccessor, 4);
4397 // Ignore the result. 4347 // Ignore the result.
4398 break; 4348 break;
4399 } 4349 }
4400 default: UNREACHABLE(); 4350 default: UNREACHABLE();
4401 } 4351 }
4402 } 4352 }
4403 } 4353 }
4404 4354
4405 4355
4406 // Materialize the array literal 'node' in the literals array 'literals'
4407 // of the function. Leave the array boilerplate in 'boilerplate'.
4408 class DeferredArrayLiteral: public DeferredCode {
4409 public:
4410 DeferredArrayLiteral(Register boilerplate,
4411 Register literals,
4412 ArrayLiteral* node)
4413 : boilerplate_(boilerplate), literals_(literals), node_(node) {
4414 set_comment("[ DeferredArrayLiteral");
4415 }
4416
4417 void Generate();
4418
4419 private:
4420 Register boilerplate_;
4421 Register literals_;
4422 ArrayLiteral* node_;
4423 };
4424
4425
4426 void DeferredArrayLiteral::Generate() {
4427 // Since the entry is undefined we call the runtime system to
4428 // compute the literal.
4429 // Literal array (0).
4430 __ push(literals_);
4431 // Literal index (1).
4432 __ push(Immediate(Smi::FromInt(node_->literal_index())));
4433 // Constant properties (2).
4434 __ push(Immediate(node_->literals()));
4435 __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
4436 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax);
4437 }
4438
4439
4440 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 4356 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
4441 Comment cmnt(masm_, "[ ArrayLiteral"); 4357 Comment cmnt(masm_, "[ ArrayLiteral");
4442 4358
4443 // Retrieve the literals array and check the allocated entry. Begin 4359 // Load a writable copy of the function of this activation in a
4444 // with a writable copy of the function of this activation in a
4445 // register. 4360 // register.
4446 frame_->PushFunction(); 4361 frame_->PushFunction();
4447 Result literals = frame_->Pop(); 4362 Result literals = frame_->Pop();
4448 literals.ToRegister(); 4363 literals.ToRegister();
4449 frame_->Spill(literals.reg()); 4364 frame_->Spill(literals.reg());
4450 4365
4451 // Load the literals array of the function. 4366 // Load the literals array of the function.
4452 __ mov(literals.reg(), 4367 __ mov(literals.reg(),
4453 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); 4368 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
4454 4369
4455 // Load the literal at the ast saved index. 4370 frame_->Push(&literals);
4456 Result boilerplate = allocator_->Allocate(); 4371 frame_->Push(Smi::FromInt(node->literal_index()));
4457 ASSERT(boilerplate.is_valid()); 4372 frame_->Push(node->constant_elements());
4458 int literal_offset =
4459 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
4460 __ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset));
4461
4462 // Check whether we need to materialize the object literal boilerplate.
4463 // If so, jump to the deferred code passing the literals array.
4464 DeferredArrayLiteral* deferred =
4465 new DeferredArrayLiteral(boilerplate.reg(), literals.reg(), node);
4466 __ cmp(boilerplate.reg(), Factory::undefined_value());
4467 deferred->Branch(equal);
4468 deferred->BindExit();
4469 literals.Unuse();
4470
4471 // Push the resulting array literal boilerplate on the stack.
4472 frame_->Push(&boilerplate);
4473
4474 // Clone the boilerplate object.
4475 int length = node->values()->length(); 4373 int length = node->values()->length();
4476 Result clone; 4374 Result clone;
4477 if (node->depth() == 1) { 4375 if (node->depth() > 1) {
4478 if (length <= FastCloneShallowArrayStub::kMaximumLength) { 4376 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
4479 FastCloneShallowArrayStub stub(length); 4377 } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
4480 clone = frame_->CallStub(&stub, 1); 4378 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
4481 } else {
4482 clone = frame_->CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1);
4483 }
4484 } else { 4379 } else {
4485 clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); 4380 FastCloneShallowArrayStub stub(length);
4381 clone = frame_->CallStub(&stub, 3);
4486 } 4382 }
4487 // Push the newly cloned literal object as the result.
4488 frame_->Push(&clone); 4383 frame_->Push(&clone);
4489 4384
4490 // Generate code to set the elements in the array that are not 4385 // Generate code to set the elements in the array that are not
4491 // literals. 4386 // literals.
4492 for (int i = 0; i < length; i++) { 4387 for (int i = 0; i < length; i++) {
4493 Expression* value = node->values()->at(i); 4388 Expression* value = node->values()->at(i);
4494 4389
4495 // If value is a literal the property value is already set in the 4390 // If value is a literal the property value is already set in the
4496 // boilerplate object. 4391 // boilerplate object.
4497 if (value->AsLiteral() != NULL) continue; 4392 if (value->AsLiteral() != NULL) continue;
(...skipping 2260 matching lines...) Expand 10 before | Expand all | Expand 10 after
6758 // Need to collect. Call into runtime system. 6653 // Need to collect. Call into runtime system.
6759 __ bind(&gc); 6654 __ bind(&gc);
6760 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); 6655 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1);
6761 } 6656 }
6762 6657
6763 6658
6764 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 6659 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
6765 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0; 6660 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0;
6766 int size = JSArray::kSize + elements_size; 6661 int size = JSArray::kSize + elements_size;
6767 6662
6663 // Load boilerplate object into ecx and check if we need to create a
6664 // boilerplate.
6665 __ mov(ecx, Operand(esp, 3 * kPointerSize));
6666 __ mov(eax, Operand(esp, 2 * kPointerSize));
6667 ASSERT(kPointerSize == 4);
6668 __ mov(ecx, FieldOperand(ecx,
6669 eax,
6670 times_2,
6671 FixedArray::kHeaderSize));
6672 __ cmp(ecx, Factory::undefined_value());
6673 Label slow_case;
6674 __ j(equal, &slow_case);
6675
6676
6768 // Allocate both the JS array and the elements array in one big 6677 // Allocate both the JS array and the elements array in one big
6769 // allocation. This avoid multiple limit checks. 6678 // allocation. This avoids multiple limit checks.
6770 Label gc; 6679 __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT);
6771 __ AllocateInNewSpace(size, eax, ebx, ecx, &gc, TAG_OBJECT);
6772
6773 // Get the boilerplate from the stack.
6774 __ mov(ecx, Operand(esp, 1 * kPointerSize));
6775 6680
6776 // Copy the JS array part. 6681 // Copy the JS array part.
6777 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 6682 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
6778 if ((i != JSArray::kElementsOffset) || (length_ == 0)) { 6683 if ((i != JSArray::kElementsOffset) || (length_ == 0)) {
6779 __ mov(ebx, FieldOperand(ecx, i)); 6684 __ mov(ebx, FieldOperand(ecx, i));
6780 __ mov(FieldOperand(eax, i), ebx); 6685 __ mov(FieldOperand(eax, i), ebx);
6781 } 6686 }
6782 } 6687 }
6783 6688
6784 if (length_ > 0) { 6689 if (length_ > 0) {
6785 // Get hold of the elements array of the boilerplate and setup the 6690 // Get hold of the elements array of the boilerplate and setup the
6786 // elements pointer in the resulting object. 6691 // elements pointer in the resulting object.
6787 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset)); 6692 __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
6788 __ lea(edx, Operand(eax, JSArray::kSize)); 6693 __ lea(edx, Operand(eax, JSArray::kSize));
6789 __ mov(FieldOperand(eax, JSArray::kElementsOffset), edx); 6694 __ mov(FieldOperand(eax, JSArray::kElementsOffset), edx);
6790 6695
6791 // Copy the elements array. 6696 // Copy the elements array.
6792 for (int i = 0; i < elements_size; i += kPointerSize) { 6697 for (int i = 0; i < elements_size; i += kPointerSize) {
6793 __ mov(ebx, FieldOperand(ecx, i)); 6698 __ mov(ebx, FieldOperand(ecx, i));
6794 __ mov(FieldOperand(edx, i), ebx); 6699 __ mov(FieldOperand(edx, i), ebx);
6795 } 6700 }
6796 } 6701 }
6797 6702
6798 // Return and remove the on-stack parameter. 6703 // Return and remove the on-stack parameters.
6799 __ ret(1 * kPointerSize); 6704 __ ret(3 * kPointerSize);
6800 6705
6801 __ bind(&gc); 6706 __ bind(&slow_case);
6802 ExternalReference runtime(Runtime::kCloneShallowLiteralBoilerplate); 6707 ExternalReference runtime(Runtime::kCreateArrayLiteralShallow);
6803 __ TailCallRuntime(runtime, 1, 1); 6708 __ TailCallRuntime(runtime, 3, 1);
6804 } 6709 }
6805 6710
6806 6711
6807 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). 6712 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).
6808 void ToBooleanStub::Generate(MacroAssembler* masm) { 6713 void ToBooleanStub::Generate(MacroAssembler* masm) {
6809 Label false_result, true_result, not_string; 6714 Label false_result, true_result, not_string;
6810 __ mov(eax, Operand(esp, 1 * kPointerSize)); 6715 __ mov(eax, Operand(esp, 1 * kPointerSize));
6811 6716
6812 // 'null' => false. 6717 // 'null' => false.
6813 __ cmp(eax, Factory::null_value()); 6718 __ cmp(eax, Factory::null_value());
(...skipping 2185 matching lines...) Expand 10 before | Expand all | Expand 10 after
8999 __ add(Operand(dest), Immediate(2)); 8904 __ add(Operand(dest), Immediate(2));
9000 } 8905 }
9001 __ sub(Operand(count), Immediate(1)); 8906 __ sub(Operand(count), Immediate(1));
9002 __ j(not_zero, &loop); 8907 __ j(not_zero, &loop);
9003 } 8908 }
9004 8909
9005 8910
9006 #undef __ 8911 #undef __
9007 8912
9008 } } // namespace v8::internal 8913 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ast.h ('k') | src/ia32/fast-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698