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 5322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5333 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 5333 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
5334 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; | 5334 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; |
5335 // else fall through. | 5335 // else fall through. |
5336 case ObjectLiteral::Property::COMPUTED: { | 5336 case ObjectLiteral::Property::COMPUTED: { |
5337 Handle<Object> key(property->key()->handle()); | 5337 Handle<Object> key(property->key()->handle()); |
5338 if (key->IsSymbol()) { | 5338 if (key->IsSymbol()) { |
5339 // Duplicate the object as the IC receiver. | 5339 // Duplicate the object as the IC receiver. |
5340 frame_->Dup(); | 5340 frame_->Dup(); |
5341 Load(property->value()); | 5341 Load(property->value()); |
5342 Result dummy = frame_->CallStoreIC(Handle<String>::cast(key), false); | 5342 Result dummy = frame_->CallStoreIC(Handle<String>::cast(key), false); |
| 5343 // A test eax instruction following the store IC call would |
| 5344 // indicate the presence of an inlined version of the |
| 5345 // store. Add a nop to indicate that there is no such |
| 5346 // inlined version. |
| 5347 __ nop(); |
5343 dummy.Unuse(); | 5348 dummy.Unuse(); |
5344 break; | 5349 break; |
5345 } | 5350 } |
5346 // Fall through | 5351 // Fall through |
5347 } | 5352 } |
5348 case ObjectLiteral::Property::PROTOTYPE: { | 5353 case ObjectLiteral::Property::PROTOTYPE: { |
5349 // Duplicate the object as an argument to the runtime call. | 5354 // Duplicate the object as an argument to the runtime call. |
5350 frame_->Dup(); | 5355 frame_->Dup(); |
5351 Load(property->key()); | 5356 Load(property->key()); |
5352 Load(property->value()); | 5357 Load(property->value()); |
(...skipping 3501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8854 } | 8859 } |
8855 ASSERT(frame()->height() == original_height - 1); | 8860 ASSERT(frame()->height() == original_height - 1); |
8856 return result; | 8861 return result; |
8857 } | 8862 } |
8858 | 8863 |
8859 | 8864 |
8860 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { | 8865 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { |
8861 #ifdef DEBUG | 8866 #ifdef DEBUG |
8862 int expected_height = frame()->height() - (is_contextual ? 1 : 2); | 8867 int expected_height = frame()->height() - (is_contextual ? 1 : 2); |
8863 #endif | 8868 #endif |
8864 Result result = frame()->CallStoreIC(name, is_contextual); | 8869 |
| 8870 Result result; |
| 8871 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { |
| 8872 result = frame()->CallStoreIC(name, is_contextual); |
| 8873 // A test eax instruction following the call signals that the inobject |
| 8874 // property case was inlined. Ensure that there is not a test eax |
| 8875 // instruction here. |
| 8876 __ nop(); |
| 8877 } else { |
| 8878 // Inline the in-object property case. |
| 8879 JumpTarget slow, done; |
| 8880 Label patch_site; |
| 8881 |
| 8882 // Get the value and receiver from the stack. |
| 8883 Result value = frame()->Pop(); |
| 8884 value.ToRegister(); |
| 8885 Result receiver = frame()->Pop(); |
| 8886 receiver.ToRegister(); |
| 8887 |
| 8888 // Allocate result register. |
| 8889 result = allocator()->Allocate(); |
| 8890 ASSERT(result.is_valid() && receiver.is_valid() && value.is_valid()); |
| 8891 |
| 8892 // Check that the receiver is a heap object. |
| 8893 __ test(receiver.reg(), Immediate(kSmiTagMask)); |
| 8894 slow.Branch(zero, &value, &receiver); |
| 8895 |
| 8896 // This is the map check instruction that will be patched (so we can't |
| 8897 // use the double underscore macro that may insert instructions). |
| 8898 // Initially use an invalid map to force a failure. |
| 8899 __ bind(&patch_site); |
| 8900 masm()->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), |
| 8901 Immediate(Factory::null_value())); |
| 8902 // This branch is always a forwards branch so it's always a fixed size |
| 8903 // which allows the assert below to succeed and patching to work. |
| 8904 slow.Branch(not_equal, &value, &receiver); |
| 8905 |
| 8906 // The delta from the patch label to the store offset must be |
| 8907 // statically known. |
| 8908 ASSERT(masm()->SizeOfCodeGeneratedSince(&patch_site) == |
| 8909 StoreIC::kOffsetToStoreInstruction); |
| 8910 |
| 8911 // The initial (invalid) offset has to be large enough to force a 32-bit |
| 8912 // instruction encoding to allow patching with an arbitrary offset. Use |
| 8913 // kMaxInt (minus kHeapObjectTag). |
| 8914 int offset = kMaxInt; |
| 8915 __ mov(FieldOperand(receiver.reg(), offset), value.reg()); |
| 8916 __ mov(result.reg(), Operand(value.reg())); |
| 8917 |
| 8918 // Allocate scratch register for write barrier. |
| 8919 Result scratch = allocator()->Allocate(); |
| 8920 ASSERT(scratch.is_valid() && |
| 8921 result.is_valid() && |
| 8922 receiver.is_valid() && |
| 8923 value.is_valid()); |
| 8924 |
| 8925 // The write barrier clobbers all input registers, so spill the |
| 8926 // receiver and the value. |
| 8927 frame_->Spill(receiver.reg()); |
| 8928 frame_->Spill(value.reg()); |
| 8929 |
| 8930 // Update the write barrier. To save instructions in the inlined |
| 8931 // version we do not filter smis. |
| 8932 Label skip_write_barrier; |
| 8933 __ InNewSpace(receiver.reg(), value.reg(), equal, &skip_write_barrier); |
| 8934 int delta_to_record_write = masm_->SizeOfCodeGeneratedSince(&patch_site); |
| 8935 __ lea(scratch.reg(), Operand(receiver.reg(), offset)); |
| 8936 __ RecordWriteHelper(receiver.reg(), scratch.reg(), value.reg()); |
| 8937 if (FLAG_debug_code) { |
| 8938 __ mov(receiver.reg(), Immediate(BitCast<int32_t>(kZapValue))); |
| 8939 __ mov(value.reg(), Immediate(BitCast<int32_t>(kZapValue))); |
| 8940 __ mov(scratch.reg(), Immediate(BitCast<int32_t>(kZapValue))); |
| 8941 } |
| 8942 __ bind(&skip_write_barrier); |
| 8943 value.Unuse(); |
| 8944 scratch.Unuse(); |
| 8945 receiver.Unuse(); |
| 8946 done.Jump(&result); |
| 8947 |
| 8948 slow.Bind(&value, &receiver); |
| 8949 frame()->Push(&receiver); |
| 8950 frame()->Push(&value); |
| 8951 result = frame()->CallStoreIC(name, is_contextual); |
| 8952 // Encode the offset to the map check instruction and the offset |
| 8953 // to the write barrier store address computation in a test eax |
| 8954 // instruction. |
| 8955 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site); |
| 8956 __ test(eax, |
| 8957 Immediate((delta_to_record_write << 16) | delta_to_patch_site)); |
| 8958 done.Bind(&result); |
| 8959 } |
8865 | 8960 |
8866 ASSERT_EQ(expected_height, frame()->height()); | 8961 ASSERT_EQ(expected_height, frame()->height()); |
8867 return result; | 8962 return result; |
8868 } | 8963 } |
8869 | 8964 |
8870 | 8965 |
8871 Result CodeGenerator::EmitKeyedLoad() { | 8966 Result CodeGenerator::EmitKeyedLoad() { |
8872 #ifdef DEBUG | 8967 #ifdef DEBUG |
8873 int original_height = frame()->height(); | 8968 int original_height = frame()->height(); |
8874 #endif | 8969 #endif |
(...skipping 4932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13807 masm.GetCode(&desc); | 13902 masm.GetCode(&desc); |
13808 // Call the function from C++. | 13903 // Call the function from C++. |
13809 return FUNCTION_CAST<MemCopyFunction>(buffer); | 13904 return FUNCTION_CAST<MemCopyFunction>(buffer); |
13810 } | 13905 } |
13811 | 13906 |
13812 #undef __ | 13907 #undef __ |
13813 | 13908 |
13814 } } // namespace v8::internal | 13909 } } // namespace v8::internal |
13815 | 13910 |
13816 #endif // V8_TARGET_ARCH_IA32 | 13911 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |