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

Side by Side Diff: src/ic/ic-compiler.h

Issue 483683005: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compiler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix BUILD.gn Created 6 years, 4 months 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/ic/ic.cc ('k') | src/ic/ic-compiler.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_STUB_CACHE_H_ 5 #ifndef V8_IC_IC_COMPILER_H_
6 #define V8_STUB_CACHE_H_ 6 #define V8_IC_IC_COMPILER_H_
7 7
8 #include "src/allocation.h"
9 #include "src/arguments.h"
10 #include "src/code-stubs.h" 8 #include "src/code-stubs.h"
11 #include "src/ic-inl.h"
12 #include "src/macro-assembler.h" 9 #include "src/macro-assembler.h"
13 #include "src/objects.h" 10 #include "src/objects.h"
14 #include "src/zone-inl.h"
15 11
16 namespace v8 { 12 namespace v8 {
17 namespace internal { 13 namespace internal {
18 14
19 15
20 // The stub cache is used for megamorphic property accesses.
21 // It maps (map, name, type) to property access handlers. The cache does not
22 // need explicit invalidation when a prototype chain is modified, since the
23 // handlers verify the chain.
24
25
26 class CallOptimization; 16 class CallOptimization;
27 class SmallMapList; 17 class SmallMapList;
28 class StubCache; 18 class StubCache;
29 19
30 20
31 class SCTableReference {
32 public:
33 Address address() const { return address_; }
34
35 private:
36 explicit SCTableReference(Address address) : address_(address) {}
37
38 Address address_;
39
40 friend class StubCache;
41 };
42
43
44 class StubCache {
45 public:
46 struct Entry {
47 Name* key;
48 Code* value;
49 Map* map;
50 };
51
52 void Initialize();
53 // Access cache for entry hash(name, map).
54 Code* Set(Name* name, Map* map, Code* code);
55 Code* Get(Name* name, Map* map, Code::Flags flags);
56 // Clear the lookup table (@ mark compact collection).
57 void Clear();
58 // Collect all maps that match the name and flags.
59 void CollectMatchingMaps(SmallMapList* types,
60 Handle<Name> name,
61 Code::Flags flags,
62 Handle<Context> native_context,
63 Zone* zone);
64 // Generate code for probing the stub cache table.
65 // Arguments extra, extra2 and extra3 may be used to pass additional scratch
66 // registers. Set to no_reg if not needed.
67 void GenerateProbe(MacroAssembler* masm,
68 Code::Flags flags,
69 Register receiver,
70 Register name,
71 Register scratch,
72 Register extra,
73 Register extra2 = no_reg,
74 Register extra3 = no_reg);
75
76 enum Table {
77 kPrimary,
78 kSecondary
79 };
80
81 SCTableReference key_reference(StubCache::Table table) {
82 return SCTableReference(
83 reinterpret_cast<Address>(&first_entry(table)->key));
84 }
85
86 SCTableReference map_reference(StubCache::Table table) {
87 return SCTableReference(
88 reinterpret_cast<Address>(&first_entry(table)->map));
89 }
90
91 SCTableReference value_reference(StubCache::Table table) {
92 return SCTableReference(
93 reinterpret_cast<Address>(&first_entry(table)->value));
94 }
95
96 StubCache::Entry* first_entry(StubCache::Table table) {
97 switch (table) {
98 case StubCache::kPrimary: return StubCache::primary_;
99 case StubCache::kSecondary: return StubCache::secondary_;
100 }
101 UNREACHABLE();
102 return NULL;
103 }
104
105 Isolate* isolate() { return isolate_; }
106
107 // Setting the entry size such that the index is shifted by Name::kHashShift
108 // is convenient; shifting down the length field (to extract the hash code)
109 // automatically discards the hash bit field.
110 static const int kCacheIndexShift = Name::kHashShift;
111
112 private:
113 explicit StubCache(Isolate* isolate);
114
115 // The stub cache has a primary and secondary level. The two levels have
116 // different hashing algorithms in order to avoid simultaneous collisions
117 // in both caches. Unlike a probing strategy (quadratic or otherwise) the
118 // update strategy on updates is fairly clear and simple: Any existing entry
119 // in the primary cache is moved to the secondary cache, and secondary cache
120 // entries are overwritten.
121
122 // Hash algorithm for the primary table. This algorithm is replicated in
123 // assembler for every architecture. Returns an index into the table that
124 // is scaled by 1 << kCacheIndexShift.
125 static int PrimaryOffset(Name* name, Code::Flags flags, Map* map) {
126 STATIC_ASSERT(kCacheIndexShift == Name::kHashShift);
127 // Compute the hash of the name (use entire hash field).
128 DCHECK(name->HasHashCode());
129 uint32_t field = name->hash_field();
130 // Using only the low bits in 64-bit mode is unlikely to increase the
131 // risk of collision even if the heap is spread over an area larger than
132 // 4Gb (and not at all if it isn't).
133 uint32_t map_low32bits =
134 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
135 // We always set the in_loop bit to zero when generating the lookup code
136 // so do it here too so the hash codes match.
137 uint32_t iflags =
138 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
139 // Base the offset on a simple combination of name, flags, and map.
140 uint32_t key = (map_low32bits + field) ^ iflags;
141 return key & ((kPrimaryTableSize - 1) << kCacheIndexShift);
142 }
143
144 // Hash algorithm for the secondary table. This algorithm is replicated in
145 // assembler for every architecture. Returns an index into the table that
146 // is scaled by 1 << kCacheIndexShift.
147 static int SecondaryOffset(Name* name, Code::Flags flags, int seed) {
148 // Use the seed from the primary cache in the secondary cache.
149 uint32_t name_low32bits =
150 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
151 // We always set the in_loop bit to zero when generating the lookup code
152 // so do it here too so the hash codes match.
153 uint32_t iflags =
154 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
155 uint32_t key = (seed - name_low32bits) + iflags;
156 return key & ((kSecondaryTableSize - 1) << kCacheIndexShift);
157 }
158
159 // Compute the entry for a given offset in exactly the same way as
160 // we do in generated code. We generate an hash code that already
161 // ends in Name::kHashShift 0s. Then we multiply it so it is a multiple
162 // of sizeof(Entry). This makes it easier to avoid making mistakes
163 // in the hashed offset computations.
164 static Entry* entry(Entry* table, int offset) {
165 const int multiplier = sizeof(*table) >> Name::kHashShift;
166 return reinterpret_cast<Entry*>(
167 reinterpret_cast<Address>(table) + offset * multiplier);
168 }
169
170 static const int kPrimaryTableBits = 11;
171 static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
172 static const int kSecondaryTableBits = 9;
173 static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
174
175 Entry primary_[kPrimaryTableSize];
176 Entry secondary_[kSecondaryTableSize];
177 Isolate* isolate_;
178
179 friend class Isolate;
180 friend class SCTableReference;
181
182 DISALLOW_COPY_AND_ASSIGN(StubCache);
183 };
184
185
186 // ------------------------------------------------------------------------
187
188
189 // Support functions for IC stubs for callbacks.
190 DECLARE_RUNTIME_FUNCTION(StoreCallbackProperty);
191
192
193 // Support functions for IC stubs for interceptors.
194 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly);
195 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor);
196 DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor);
197 DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor);
198
199
200 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER }; 21 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
201 enum IcCheckType { ELEMENT, PROPERTY }; 22 enum IcCheckType { ELEMENT, PROPERTY };
202 23
203 24
204 class PropertyAccessCompiler BASE_EMBEDDED { 25 class PropertyAccessCompiler BASE_EMBEDDED {
205 public: 26 public:
206 static Builtins::Name MissBuiltin(Code::Kind kind) { 27 static Builtins::Name MissBuiltin(Code::Kind kind) {
207 switch (kind) { 28 switch (kind) {
208 case Code::LOAD_IC: 29 case Code::LOAD_IC:
209 return Builtins::kLoadIC_Miss; 30 return Builtins::kLoadIC_Miss;
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 Register* values); 223 Register* values);
403 224
404 // Helper function used to check that the dictionary doesn't contain 225 // Helper function used to check that the dictionary doesn't contain
405 // the property. This function may return false negatives, so miss_label 226 // the property. This function may return false negatives, so miss_label
406 // must always call a backup property check that is complete. 227 // must always call a backup property check that is complete.
407 // This function is safe to call if the receiver has fast properties. 228 // This function is safe to call if the receiver has fast properties.
408 // Name must be unique and receiver must be a heap object. 229 // Name must be unique and receiver must be a heap object.
409 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 230 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
410 Label* miss_label, 231 Label* miss_label,
411 Register receiver, 232 Register receiver,
412 Handle<Name> name, 233 Handle<Name> name, Register r0,
413 Register r0,
414 Register r1); 234 Register r1);
415 235
416 // Generate code to check that a global property cell is empty. Create 236 // Generate code to check that a global property cell is empty. Create
417 // the property cell at compilation time if no cell exists for the 237 // the property cell at compilation time if no cell exists for the
418 // property. 238 // property.
419 static void GenerateCheckPropertyCell(MacroAssembler* masm, 239 static void GenerateCheckPropertyCell(MacroAssembler* masm,
420 Handle<JSGlobalObject> global, 240 Handle<JSGlobalObject> global,
421 Handle<Name> name, 241 Handle<Name> name, Register scratch,
422 Register scratch,
423 Label* miss); 242 Label* miss);
424 243
425 // Generates code that verifies that the property holder has not changed 244 // Generates code that verifies that the property holder has not changed
426 // (checking maps of objects in the prototype chain for fast and global 245 // (checking maps of objects in the prototype chain for fast and global
427 // objects or doing negative lookup for slow objects, ensures that the 246 // objects or doing negative lookup for slow objects, ensures that the
428 // property cells for global objects are still empty) and checks that the map 247 // property cells for global objects are still empty) and checks that the map
429 // of the holder has not changed. If necessary the function also generates 248 // of the holder has not changed. If necessary the function also generates
430 // code for security check in case of global object holders. Helps to make 249 // code for security check in case of global object holders. Helps to make
431 // sure that the current IC is still valid. 250 // sure that the current IC is still valid.
432 // 251 //
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 Register receiver_reg, Register name_reg, 407 Register receiver_reg, Register name_reg,
589 Register value_reg, Register scratch1, 408 Register value_reg, Register scratch1,
590 Register scratch2, Register scratch3, 409 Register scratch2, Register scratch3,
591 Label* miss_label, Label* slow); 410 Label* miss_label, Label* slow);
592 411
593 void GenerateStoreField(LookupIterator* lookup, Register value_reg, 412 void GenerateStoreField(LookupIterator* lookup, Register value_reg,
594 Label* miss_label); 413 Label* miss_label);
595 414
596 static Builtins::Name SlowBuiltin(Code::Kind kind) { 415 static Builtins::Name SlowBuiltin(Code::Kind kind) {
597 switch (kind) { 416 switch (kind) {
598 case Code::STORE_IC: return Builtins::kStoreIC_Slow; 417 case Code::STORE_IC:
599 case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow; 418 return Builtins::kStoreIC_Slow;
600 default: UNREACHABLE(); 419 case Code::KEYED_STORE_IC:
420 return Builtins::kKeyedStoreIC_Slow;
421 default:
422 UNREACHABLE();
601 } 423 }
602 return Builtins::kStoreIC_Slow; 424 return Builtins::kStoreIC_Slow;
603 } 425 }
604 426
605 static Register value(); 427 static Register value();
606 }; 428 };
607 429
608 430
609 class ElementHandlerCompiler : public PropertyHandlerCompiler { 431 class ElementHandlerCompiler : public PropertyHandlerCompiler {
610 public: 432 public:
(...skipping 10 matching lines...) Expand all
621 static void GenerateLoadDictionaryElement(MacroAssembler* masm); 443 static void GenerateLoadDictionaryElement(MacroAssembler* masm);
622 static void GenerateStoreDictionaryElement(MacroAssembler* masm); 444 static void GenerateStoreDictionaryElement(MacroAssembler* masm);
623 }; 445 };
624 446
625 447
626 // Holds information about possible function call optimizations. 448 // Holds information about possible function call optimizations.
627 class CallOptimization BASE_EMBEDDED { 449 class CallOptimization BASE_EMBEDDED {
628 public: 450 public:
629 explicit CallOptimization(Handle<JSFunction> function); 451 explicit CallOptimization(Handle<JSFunction> function);
630 452
631 bool is_constant_call() const { 453 bool is_constant_call() const { return !constant_function_.is_null(); }
632 return !constant_function_.is_null();
633 }
634 454
635 Handle<JSFunction> constant_function() const { 455 Handle<JSFunction> constant_function() const {
636 DCHECK(is_constant_call()); 456 DCHECK(is_constant_call());
637 return constant_function_; 457 return constant_function_;
638 } 458 }
639 459
640 bool is_simple_api_call() const { 460 bool is_simple_api_call() const { return is_simple_api_call_; }
641 return is_simple_api_call_;
642 }
643 461
644 Handle<FunctionTemplateInfo> expected_receiver_type() const { 462 Handle<FunctionTemplateInfo> expected_receiver_type() const {
645 DCHECK(is_simple_api_call()); 463 DCHECK(is_simple_api_call());
646 return expected_receiver_type_; 464 return expected_receiver_type_;
647 } 465 }
648 466
649 Handle<CallHandlerInfo> api_call_info() const { 467 Handle<CallHandlerInfo> api_call_info() const {
650 DCHECK(is_simple_api_call()); 468 DCHECK(is_simple_api_call());
651 return api_call_info_; 469 return api_call_info_;
652 } 470 }
653 471
654 enum HolderLookup { 472 enum HolderLookup { kHolderNotFound, kHolderIsReceiver, kHolderFound };
655 kHolderNotFound,
656 kHolderIsReceiver,
657 kHolderFound
658 };
659 Handle<JSObject> LookupHolderOfExpectedType( 473 Handle<JSObject> LookupHolderOfExpectedType(
660 Handle<Map> receiver_map, 474 Handle<Map> receiver_map, HolderLookup* holder_lookup) const;
661 HolderLookup* holder_lookup) const;
662 475
663 // Check if the api holder is between the receiver and the holder. 476 // Check if the api holder is between the receiver and the holder.
664 bool IsCompatibleReceiver(Handle<Object> receiver, 477 bool IsCompatibleReceiver(Handle<Object> receiver,
665 Handle<JSObject> holder) const; 478 Handle<JSObject> holder) const;
666 479
667 private: 480 private:
668 void Initialize(Handle<JSFunction> function); 481 void Initialize(Handle<JSFunction> function);
669 482
670 // Determines whether the given function can be called using the 483 // Determines whether the given function can be called using the
671 // fast api call builtin. 484 // fast api call builtin.
672 void AnalyzePossibleApiFunction(Handle<JSFunction> function); 485 void AnalyzePossibleApiFunction(Handle<JSFunction> function);
673 486
674 Handle<JSFunction> constant_function_; 487 Handle<JSFunction> constant_function_;
675 bool is_simple_api_call_; 488 bool is_simple_api_call_;
676 Handle<FunctionTemplateInfo> expected_receiver_type_; 489 Handle<FunctionTemplateInfo> expected_receiver_type_;
677 Handle<CallHandlerInfo> api_call_info_; 490 Handle<CallHandlerInfo> api_call_info_;
678 }; 491 };
492 }
493 } // namespace v8::internal
679 494
680 495 #endif // V8_IC_IC_COMPILER_H_
681 } } // namespace v8::internal
682
683 #endif // V8_STUB_CACHE_H_
OLDNEW
« no previous file with comments | « src/ic/ic.cc ('k') | src/ic/ic-compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698