| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |