| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 } | 125 } |
| 126 | 126 |
| 127 | 127 |
| 128 TypeInfoCodeGenState::~TypeInfoCodeGenState() { | 128 TypeInfoCodeGenState::~TypeInfoCodeGenState() { |
| 129 owner()->set_type_info(slot_, old_type_info_); | 129 owner()->set_type_info(slot_, old_type_info_); |
| 130 } | 130 } |
| 131 | 131 |
| 132 // ------------------------------------------------------------------------- | 132 // ------------------------------------------------------------------------- |
| 133 // CodeGenerator implementation | 133 // CodeGenerator implementation |
| 134 | 134 |
| 135 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 135 int CodeGenerator::inlined_write_barrier_size_ = -1; | 136 int CodeGenerator::inlined_write_barrier_size_ = -1; |
| 137 #endif |
| 136 | 138 |
| 137 CodeGenerator::CodeGenerator(MacroAssembler* masm) | 139 CodeGenerator::CodeGenerator(MacroAssembler* masm) |
| 138 : deferred_(8), | 140 : deferred_(8), |
| 139 masm_(masm), | 141 masm_(masm), |
| 140 info_(NULL), | 142 info_(NULL), |
| 141 frame_(NULL), | 143 frame_(NULL), |
| 142 allocator_(NULL), | 144 allocator_(NULL), |
| 143 cc_reg_(al), | 145 cc_reg_(al), |
| 144 state_(NULL), | 146 state_(NULL), |
| 145 loop_nesting_(0), | 147 loop_nesting_(0), |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 // the function. | 251 // the function. |
| 250 frame_->AssertIsSpilled(); | 252 frame_->AssertIsSpilled(); |
| 251 for (int i = 0; i < scope()->num_parameters(); i++) { | 253 for (int i = 0; i < scope()->num_parameters(); i++) { |
| 252 Variable* par = scope()->parameter(i); | 254 Variable* par = scope()->parameter(i); |
| 253 Slot* slot = par->AsSlot(); | 255 Slot* slot = par->AsSlot(); |
| 254 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 256 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 255 ASSERT(!scope()->is_global_scope()); // No params in global scope. | 257 ASSERT(!scope()->is_global_scope()); // No params in global scope. |
| 256 __ ldr(r1, frame_->ParameterAt(i)); | 258 __ ldr(r1, frame_->ParameterAt(i)); |
| 257 // Loads r2 with context; used below in RecordWrite. | 259 // Loads r2 with context; used below in RecordWrite. |
| 258 __ str(r1, SlotOperand(slot, r2)); | 260 __ str(r1, SlotOperand(slot, r2)); |
| 261 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 259 // Load the offset into r3. | 262 // Load the offset into r3. |
| 260 int slot_offset = | 263 int slot_offset = |
| 261 FixedArray::kHeaderSize + slot->index() * kPointerSize; | 264 FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 262 __ RecordWrite(r2, Operand(slot_offset), r3, r1); | 265 __ RecordWrite(r2, Operand(slot_offset), r3, r1); |
| 266 #endif |
| 263 } | 267 } |
| 264 } | 268 } |
| 265 } | 269 } |
| 266 | 270 |
| 267 // Store the arguments object. This must happen after context | 271 // Store the arguments object. This must happen after context |
| 268 // initialization because the arguments object may be stored in | 272 // initialization because the arguments object may be stored in |
| 269 // the context. | 273 // the context. |
| 270 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | 274 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { |
| 271 StoreArgumentsObject(true); | 275 StoreArgumentsObject(true); |
| 272 } | 276 } |
| (...skipping 3055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3328 // calling this code. r2 may be loaded with context; used below in | 3332 // calling this code. r2 may be loaded with context; used below in |
| 3329 // RecordWrite. | 3333 // RecordWrite. |
| 3330 Register tos = frame_->Peek(); | 3334 Register tos = frame_->Peek(); |
| 3331 __ str(tos, SlotOperand(slot, scratch)); | 3335 __ str(tos, SlotOperand(slot, scratch)); |
| 3332 if (slot->type() == Slot::CONTEXT) { | 3336 if (slot->type() == Slot::CONTEXT) { |
| 3333 // Skip write barrier if the written value is a smi. | 3337 // Skip write barrier if the written value is a smi. |
| 3334 __ tst(tos, Operand(kSmiTagMask)); | 3338 __ tst(tos, Operand(kSmiTagMask)); |
| 3335 // We don't use tos any more after here. | 3339 // We don't use tos any more after here. |
| 3336 exit.Branch(eq); | 3340 exit.Branch(eq); |
| 3337 // scratch is loaded with context when calling SlotOperand above. | 3341 // scratch is loaded with context when calling SlotOperand above. |
| 3342 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 3338 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 3343 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 3339 // We need an extra register. Until we have a way to do that in the | 3344 // We need an extra register. Until we have a way to do that in the |
| 3340 // virtual frame we will cheat and ask for a free TOS register. | 3345 // virtual frame we will cheat and ask for a free TOS register. |
| 3341 Register scratch3 = frame_->GetTOSRegister(); | 3346 Register scratch3 = frame_->GetTOSRegister(); |
| 3342 __ RecordWrite(scratch, Operand(offset), scratch2, scratch3); | 3347 __ RecordWrite(scratch, Operand(offset), scratch2, scratch3); |
| 3348 #endif |
| 3343 } | 3349 } |
| 3344 // If we definitely did not jump over the assignment, we do not need | 3350 // If we definitely did not jump over the assignment, we do not need |
| 3345 // to bind the exit label. Doing so can defeat peephole | 3351 // to bind the exit label. Doing so can defeat peephole |
| 3346 // optimization. | 3352 // optimization. |
| 3347 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { | 3353 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { |
| 3348 exit.Bind(); | 3354 exit.Bind(); |
| 3349 } | 3355 } |
| 3350 } | 3356 } |
| 3351 } | 3357 } |
| 3352 | 3358 |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3720 // Fetch the object literal. | 3726 // Fetch the object literal. |
| 3721 frame_->SpillAllButCopyTOSToR1(); | 3727 frame_->SpillAllButCopyTOSToR1(); |
| 3722 | 3728 |
| 3723 // Get the elements array. | 3729 // Get the elements array. |
| 3724 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 3730 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| 3725 | 3731 |
| 3726 // Write to the indexed properties array. | 3732 // Write to the indexed properties array. |
| 3727 int offset = i * kPointerSize + FixedArray::kHeaderSize; | 3733 int offset = i * kPointerSize + FixedArray::kHeaderSize; |
| 3728 __ str(r0, FieldMemOperand(r1, offset)); | 3734 __ str(r0, FieldMemOperand(r1, offset)); |
| 3729 | 3735 |
| 3736 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 3730 // Update the write barrier for the array address. | 3737 // Update the write barrier for the array address. |
| 3731 __ RecordWrite(r1, Operand(offset), r3, r2); | 3738 __ RecordWrite(r1, Operand(offset), r3, r2); |
| 3739 #endif |
| 3732 } | 3740 } |
| 3733 ASSERT_EQ(original_height + 1, frame_->height()); | 3741 ASSERT_EQ(original_height + 1, frame_->height()); |
| 3734 } | 3742 } |
| 3735 | 3743 |
| 3736 | 3744 |
| 3737 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { | 3745 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
| 3738 #ifdef DEBUG | 3746 #ifdef DEBUG |
| 3739 int original_height = frame_->height(); | 3747 int original_height = frame_->height(); |
| 3740 #endif | 3748 #endif |
| 3741 // Call runtime routine to allocate the catch extension object and | 3749 // Call runtime routine to allocate the catch extension object and |
| (...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4541 Register value = frame_->PopToRegister(); | 4549 Register value = frame_->PopToRegister(); |
| 4542 Register object = frame_->PopToRegister(value); | 4550 Register object = frame_->PopToRegister(value); |
| 4543 // if (object->IsSmi()) return object. | 4551 // if (object->IsSmi()) return object. |
| 4544 __ tst(object, Operand(kSmiTagMask)); | 4552 __ tst(object, Operand(kSmiTagMask)); |
| 4545 leave.Branch(eq); | 4553 leave.Branch(eq); |
| 4546 // It is a heap object - get map. If (!object->IsJSValue()) return the object. | 4554 // It is a heap object - get map. If (!object->IsJSValue()) return the object. |
| 4547 __ CompareObjectType(object, scratch1, scratch1, JS_VALUE_TYPE); | 4555 __ CompareObjectType(object, scratch1, scratch1, JS_VALUE_TYPE); |
| 4548 leave.Branch(ne); | 4556 leave.Branch(ne); |
| 4549 // Store the value. | 4557 // Store the value. |
| 4550 __ str(value, FieldMemOperand(object, JSValue::kValueOffset)); | 4558 __ str(value, FieldMemOperand(object, JSValue::kValueOffset)); |
| 4559 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 4551 // Update the write barrier. | 4560 // Update the write barrier. |
| 4552 __ RecordWrite(object, | 4561 __ RecordWrite(object, |
| 4553 Operand(JSValue::kValueOffset - kHeapObjectTag), | 4562 Operand(JSValue::kValueOffset - kHeapObjectTag), |
| 4554 scratch1, | 4563 scratch1, |
| 4555 scratch2); | 4564 scratch2); |
| 4565 #endif |
| 4556 // Leave. | 4566 // Leave. |
| 4557 leave.Bind(); | 4567 leave.Bind(); |
| 4558 frame_->EmitPush(value); | 4568 frame_->EmitPush(value); |
| 4559 } | 4569 } |
| 4560 | 4570 |
| 4561 | 4571 |
| 4562 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 4572 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
| 4563 ASSERT(args->length() == 1); | 4573 ASSERT(args->length() == 1); |
| 4564 Load(args->at(0)); | 4574 Load(args->at(0)); |
| 4565 Register reg = frame_->PopToRegister(); | 4575 Register reg = frame_->PopToRegister(); |
| (...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5599 __ add(index2, tmp2, Operand(index2, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5609 __ add(index2, tmp2, Operand(index2, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 5600 | 5610 |
| 5601 // Swap elements. | 5611 // Swap elements. |
| 5602 Register tmp3 = object; | 5612 Register tmp3 = object; |
| 5603 object = no_reg; | 5613 object = no_reg; |
| 5604 __ ldr(tmp3, MemOperand(tmp1, index1)); | 5614 __ ldr(tmp3, MemOperand(tmp1, index1)); |
| 5605 __ ldr(tmp2, MemOperand(tmp1, index2)); | 5615 __ ldr(tmp2, MemOperand(tmp1, index2)); |
| 5606 __ str(tmp3, MemOperand(tmp1, index2)); | 5616 __ str(tmp3, MemOperand(tmp1, index2)); |
| 5607 __ str(tmp2, MemOperand(tmp1, index1)); | 5617 __ str(tmp2, MemOperand(tmp1, index1)); |
| 5608 | 5618 |
| 5619 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 5609 Label done; | 5620 Label done; |
| 5610 __ InNewSpace(tmp1, tmp2, eq, &done); | 5621 __ InNewSpace(tmp1, tmp2, eq, &done); |
| 5611 // Possible optimization: do a check that both values are Smis | 5622 // Possible optimization: do a check that both values are Smis |
| 5612 // (or them and test against Smi mask.) | 5623 // (or them and test against Smi mask.) |
| 5613 | 5624 |
| 5614 __ mov(tmp2, tmp1); | 5625 __ mov(tmp2, tmp1); |
| 5615 RecordWriteStub recordWrite1(tmp1, index1, tmp3); | 5626 RecordWriteStub recordWrite1(tmp1, index1, tmp3); |
| 5616 __ CallStub(&recordWrite1); | 5627 __ CallStub(&recordWrite1); |
| 5617 | 5628 |
| 5618 RecordWriteStub recordWrite2(tmp2, index2, tmp3); | 5629 RecordWriteStub recordWrite2(tmp2, index2, tmp3); |
| 5619 __ CallStub(&recordWrite2); | 5630 __ CallStub(&recordWrite2); |
| 5620 | 5631 |
| 5621 __ bind(&done); | 5632 __ bind(&done); |
| 5633 #endif |
| 5622 | 5634 |
| 5623 deferred->BindExit(); | 5635 deferred->BindExit(); |
| 5624 __ LoadRoot(tmp1, Heap::kUndefinedValueRootIndex); | 5636 __ LoadRoot(tmp1, Heap::kUndefinedValueRootIndex); |
| 5625 frame_->EmitPush(tmp1); | 5637 frame_->EmitPush(tmp1); |
| 5626 } | 5638 } |
| 5627 | 5639 |
| 5628 | 5640 |
| 5629 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) { | 5641 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) { |
| 5630 Comment cmnt(masm_, "[ GenerateCallFunction"); | 5642 Comment cmnt(masm_, "[ GenerateCallFunction"); |
| 5631 | 5643 |
| (...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6957 __ mov(scratch0, Operand(Factory::null_value())); | 6969 __ mov(scratch0, Operand(Factory::null_value())); |
| 6958 __ cmp(scratch0, scratch1); | 6970 __ cmp(scratch0, scratch1); |
| 6959 deferred->Branch(ne); | 6971 deferred->Branch(ne); |
| 6960 | 6972 |
| 6961 int offset = 0; | 6973 int offset = 0; |
| 6962 __ str(value, MemOperand(receiver, offset)); | 6974 __ str(value, MemOperand(receiver, offset)); |
| 6963 | 6975 |
| 6964 // Update the write barrier and record its size. We do not use | 6976 // Update the write barrier and record its size. We do not use |
| 6965 // the RecordWrite macro here because we want the offset | 6977 // the RecordWrite macro here because we want the offset |
| 6966 // addition instruction first to make it easy to patch. | 6978 // addition instruction first to make it easy to patch. |
| 6979 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 6967 Label record_write_start, record_write_done; | 6980 Label record_write_start, record_write_done; |
| 6968 __ bind(&record_write_start); | 6981 __ bind(&record_write_start); |
| 6969 // Add offset into the object. | 6982 // Add offset into the object. |
| 6970 __ add(scratch0, receiver, Operand(offset)); | 6983 __ add(scratch0, receiver, Operand(offset)); |
| 6971 // Test that the object is not in the new space. We cannot set | 6984 // Test that the object is not in the new space. We cannot set |
| 6972 // region marks for new space pages. | 6985 // region marks for new space pages. |
| 6973 __ InNewSpace(receiver, scratch1, eq, &record_write_done); | 6986 __ InNewSpace(receiver, scratch1, eq, &record_write_done); |
| 6974 // Record the actual write. | 6987 // Record the actual write. |
| 6975 __ RecordWriteHelper(receiver, scratch0, scratch1); | 6988 __ RecordWriteHelper(receiver, scratch0, scratch1); |
| 6976 __ bind(&record_write_done); | 6989 __ bind(&record_write_done); |
| 6977 // Clobber all input registers when running with the debug-code flag | 6990 // Clobber all input registers when running with the debug-code flag |
| 6978 // turned on to provoke errors. | 6991 // turned on to provoke errors. |
| 6979 if (FLAG_debug_code) { | 6992 if (FLAG_debug_code) { |
| 6980 __ mov(receiver, Operand(BitCast<int32_t>(kZapValue))); | 6993 __ mov(receiver, Operand(BitCast<int32_t>(kZapValue))); |
| 6981 __ mov(scratch0, Operand(BitCast<int32_t>(kZapValue))); | 6994 __ mov(scratch0, Operand(BitCast<int32_t>(kZapValue))); |
| 6982 __ mov(scratch1, Operand(BitCast<int32_t>(kZapValue))); | 6995 __ mov(scratch1, Operand(BitCast<int32_t>(kZapValue))); |
| 6983 } | 6996 } |
| 6984 // Check that this is the first inlined write barrier or that | 6997 // Check that this is the first inlined write barrier or that |
| 6985 // this inlined write barrier has the same size as all the other | 6998 // this inlined write barrier has the same size as all the other |
| 6986 // inlined write barriers. | 6999 // inlined write barriers. |
| 6987 ASSERT((inlined_write_barrier_size_ == -1) || | 7000 ASSERT((inlined_write_barrier_size_ == -1) || |
| 6988 (inlined_write_barrier_size_ == | 7001 (inlined_write_barrier_size_ == |
| 6989 masm()->InstructionsGeneratedSince(&record_write_start))); | 7002 masm()->InstructionsGeneratedSince(&record_write_start))); |
| 6990 inlined_write_barrier_size_ = | 7003 inlined_write_barrier_size_ = |
| 6991 masm()->InstructionsGeneratedSince(&record_write_start); | 7004 masm()->InstructionsGeneratedSince(&record_write_start); |
| 7005 #endif |
| 6992 | 7006 |
| 6993 // Make sure that the expected number of instructions are generated. | 7007 // Make sure that the expected number of instructions are generated. |
| 6994 ASSERT_EQ(GetInlinedNamedStoreInstructionsAfterPatch(), | 7008 ASSERT_EQ(GetInlinedNamedStoreInstructionsAfterPatch(), |
| 6995 masm()->InstructionsGeneratedSince(&check_inlined_codesize)); | 7009 masm()->InstructionsGeneratedSince(&check_inlined_codesize)); |
| 6996 } | 7010 } |
| 6997 deferred->BindExit(); | 7011 deferred->BindExit(); |
| 6998 } | 7012 } |
| 6999 ASSERT_EQ(expected_height, frame()->height()); | 7013 ASSERT_EQ(expected_height, frame()->height()); |
| 7000 } | 7014 } |
| 7001 | 7015 |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7364 BinaryOpIC::GetName(runtime_operands_type_)); | 7378 BinaryOpIC::GetName(runtime_operands_type_)); |
| 7365 return name_; | 7379 return name_; |
| 7366 } | 7380 } |
| 7367 | 7381 |
| 7368 | 7382 |
| 7369 #undef __ | 7383 #undef __ |
| 7370 | 7384 |
| 7371 } } // namespace v8::internal | 7385 } } // namespace v8::internal |
| 7372 | 7386 |
| 7373 #endif // V8_TARGET_ARCH_ARM | 7387 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |