| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 25 matching lines...) Expand all Loading... |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 #define __ ACCESS_MASM(masm) | 39 #define __ ACCESS_MASM(masm) |
| 40 | 40 |
| 41 | 41 |
| 42 static void ProbeTable(Isolate* isolate, | 42 static void ProbeTable(Isolate* isolate, |
| 43 MacroAssembler* masm, | 43 MacroAssembler* masm, |
| 44 Code::Flags flags, | 44 Code::Flags flags, |
| 45 StubCache::Table table, | 45 StubCache::Table table, |
| 46 Register receiver, |
| 46 Register name, | 47 Register name, |
| 47 Register offset) { | 48 Register offset) { |
| 48 ASSERT_EQ(8, kPointerSize); | 49 ASSERT_EQ(8, kPointerSize); |
| 49 ASSERT_EQ(16, sizeof(StubCache::Entry)); | 50 ASSERT_EQ(24, sizeof(StubCache::Entry)); |
| 50 // The offset register holds the entry offset times four (due to masking | 51 // The offset register holds the entry offset times four (due to masking |
| 51 // and shifting optimizations). | 52 // and shifting optimizations). |
| 52 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); | 53 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); |
| 54 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
| 53 Label miss; | 55 Label miss; |
| 54 | 56 |
| 57 // Multiply by 3. |
| 58 __ lea(offset, Operand(offset, offset, times_2, 0)); |
| 59 |
| 55 __ LoadAddress(kScratchRegister, key_offset); | 60 __ LoadAddress(kScratchRegister, key_offset); |
| 61 |
| 56 // Check that the key in the entry matches the name. | 62 // Check that the key in the entry matches the name. |
| 57 // Multiply entry offset by 16 to get the entry address. Since the | 63 // Multiply entry offset by 16 to get the entry address. Since the |
| 58 // offset register already holds the entry offset times four, multiply | 64 // offset register already holds the entry offset times four, multiply |
| 59 // by a further four. | 65 // by a further four. |
| 60 __ cmpl(name, Operand(kScratchRegister, offset, times_4, 0)); | 66 __ cmpl(name, Operand(kScratchRegister, offset, times_2, 0)); |
| 61 __ j(not_equal, &miss); | 67 __ j(not_equal, &miss); |
| 68 |
| 69 // Get the map entry from the cache. |
| 70 // Use key_offset + kPointerSize * 2, rather than loading map_offset. |
| 71 __ movq(kScratchRegister, |
| 72 Operand(kScratchRegister, offset, times_2, kPointerSize * 2)); |
| 73 __ cmpq(kScratchRegister, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 74 __ j(not_equal, &miss); |
| 75 |
| 62 // Get the code entry from the cache. | 76 // Get the code entry from the cache. |
| 63 // Use key_offset + kPointerSize, rather than loading value_offset. | 77 __ LoadAddress(kScratchRegister, value_offset); |
| 64 __ movq(kScratchRegister, | 78 __ movq(kScratchRegister, |
| 65 Operand(kScratchRegister, offset, times_4, kPointerSize)); | 79 Operand(kScratchRegister, offset, times_2, 0)); |
| 80 |
| 66 // Check that the flags match what we're looking for. | 81 // Check that the flags match what we're looking for. |
| 67 __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset)); | 82 __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset)); |
| 68 __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup)); | 83 __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup)); |
| 69 __ cmpl(offset, Immediate(flags)); | 84 __ cmpl(offset, Immediate(flags)); |
| 70 __ j(not_equal, &miss); | 85 __ j(not_equal, &miss); |
| 71 | 86 |
| 87 #ifdef DEBUG |
| 88 if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { |
| 89 __ jmp(&miss); |
| 90 } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { |
| 91 __ jmp(&miss); |
| 92 } |
| 93 #endif |
| 94 |
| 72 // Jump to the first instruction in the code stub. | 95 // Jump to the first instruction in the code stub. |
| 73 __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 96 __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 74 __ jmp(kScratchRegister); | 97 __ jmp(kScratchRegister); |
| 75 | 98 |
| 76 __ bind(&miss); | 99 __ bind(&miss); |
| 77 } | 100 } |
| 78 | 101 |
| 79 | 102 |
| 80 // Helper function used to check that the dictionary doesn't contain | 103 // Helper function used to check that the dictionary doesn't contain |
| 81 // the property. This function may return false negatives, so miss_label | 104 // the property. This function may return false negatives, so miss_label |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 150 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 128 } | 151 } |
| 129 | 152 |
| 130 | 153 |
| 131 void StubCache::GenerateProbe(MacroAssembler* masm, | 154 void StubCache::GenerateProbe(MacroAssembler* masm, |
| 132 Code::Flags flags, | 155 Code::Flags flags, |
| 133 Register receiver, | 156 Register receiver, |
| 134 Register name, | 157 Register name, |
| 135 Register scratch, | 158 Register scratch, |
| 136 Register extra, | 159 Register extra, |
| 137 Register extra2) { | 160 Register extra2, |
| 161 Register extra3) { |
| 138 Isolate* isolate = masm->isolate(); | 162 Isolate* isolate = masm->isolate(); |
| 139 Label miss; | 163 Label miss; |
| 140 USE(extra); // The register extra is not used on the X64 platform. | 164 USE(extra); // The register extra is not used on the X64 platform. |
| 141 USE(extra2); // The register extra2 is not used on the X64 platform. | 165 USE(extra2); // The register extra2 is not used on the X64 platform. |
| 142 // Make sure that code is valid. The shifting code relies on the | 166 USE(extra3); // The register extra2 is not used on the X64 platform. |
| 143 // entry size being 16. | 167 // Make sure that code is valid. The multiplying code relies on the |
| 144 ASSERT(sizeof(Entry) == 16); | 168 // entry size being 24. |
| 169 ASSERT(sizeof(Entry) == 24); |
| 145 | 170 |
| 146 // Make sure the flags do not name a specific type. | 171 // Make sure the flags do not name a specific type. |
| 147 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 172 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
| 148 | 173 |
| 149 // Make sure that there are no register conflicts. | 174 // Make sure that there are no register conflicts. |
| 150 ASSERT(!scratch.is(receiver)); | 175 ASSERT(!scratch.is(receiver)); |
| 151 ASSERT(!scratch.is(name)); | 176 ASSERT(!scratch.is(name)); |
| 152 | 177 |
| 153 // Check scratch register is valid, extra and extra2 are unused. | 178 // Check scratch register is valid, extra and extra2 are unused. |
| 154 ASSERT(!scratch.is(no_reg)); | 179 ASSERT(!scratch.is(no_reg)); |
| 155 ASSERT(extra2.is(no_reg)); | 180 ASSERT(extra2.is(no_reg)); |
| 181 ASSERT(extra3.is(no_reg)); |
| 182 |
| 183 Counters* counters = masm->isolate()->counters(); |
| 184 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); |
| 156 | 185 |
| 157 // Check that the receiver isn't a smi. | 186 // Check that the receiver isn't a smi. |
| 158 __ JumpIfSmi(receiver, &miss); | 187 __ JumpIfSmi(receiver, &miss); |
| 159 | 188 |
| 160 // Get the map of the receiver and compute the hash. | 189 // Get the map of the receiver and compute the hash. |
| 161 __ movl(scratch, FieldOperand(name, String::kHashFieldOffset)); | 190 __ movl(scratch, FieldOperand(name, String::kHashFieldOffset)); |
| 162 // Use only the low 32 bits of the map pointer. | 191 // Use only the low 32 bits of the map pointer. |
| 163 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 192 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 164 __ xor_(scratch, Immediate(flags)); | 193 __ xor_(scratch, Immediate(flags)); |
| 165 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize)); | 194 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize)); |
| 166 | 195 |
| 167 // Probe the primary table. | 196 // Probe the primary table. |
| 168 ProbeTable(isolate, masm, flags, kPrimary, name, scratch); | 197 ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch); |
| 169 | 198 |
| 170 // Primary miss: Compute hash for secondary probe. | 199 // Primary miss: Compute hash for secondary probe. |
| 171 __ movl(scratch, FieldOperand(name, String::kHashFieldOffset)); | 200 __ movl(scratch, FieldOperand(name, String::kHashFieldOffset)); |
| 172 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 201 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 173 __ xor_(scratch, Immediate(flags)); | 202 __ xor_(scratch, Immediate(flags)); |
| 174 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize)); | 203 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize)); |
| 175 __ subl(scratch, name); | 204 __ subl(scratch, name); |
| 176 __ addl(scratch, Immediate(flags)); | 205 __ addl(scratch, Immediate(flags)); |
| 177 __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize)); | 206 __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize)); |
| 178 | 207 |
| 179 // Probe the secondary table. | 208 // Probe the secondary table. |
| 180 ProbeTable(isolate, masm, flags, kSecondary, name, scratch); | 209 ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch); |
| 181 | 210 |
| 182 // Cache miss: Fall-through and let caller handle the miss by | 211 // Cache miss: Fall-through and let caller handle the miss by |
| 183 // entering the runtime system. | 212 // entering the runtime system. |
| 184 __ bind(&miss); | 213 __ bind(&miss); |
| 214 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 185 } | 215 } |
| 186 | 216 |
| 187 | 217 |
| 188 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 218 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, |
| 189 int index, | 219 int index, |
| 190 Register prototype) { | 220 Register prototype) { |
| 191 // Load the global or builtins object from the current context. | 221 // Load the global or builtins object from the current context. |
| 192 __ movq(prototype, | 222 __ movq(prototype, |
| 193 Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 223 Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 194 // Load the global context from the global or builtins object. | 224 // Load the global context from the global or builtins object. |
| (...skipping 3564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3759 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3789 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
| 3760 } | 3790 } |
| 3761 } | 3791 } |
| 3762 | 3792 |
| 3763 | 3793 |
| 3764 #undef __ | 3794 #undef __ |
| 3765 | 3795 |
| 3766 } } // namespace v8::internal | 3796 } } // namespace v8::internal |
| 3767 | 3797 |
| 3768 #endif // V8_TARGET_ARCH_X64 | 3798 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |