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
3 // found in the LICENSE file.
5 #ifndef V8_IC_HANDLER_COMPILER_H_
6 #define V8_IC_HANDLER_COMPILER_H_
8 #include "src/ic/access-compiler.h"
9 #include "src/ic/ic-state.h"
14 class CallOptimization;
16 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
18 class PropertyHandlerCompiler : public PropertyAccessCompiler {
20 static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
21 CacheHolderFlag cache_holder, Code::StubType type);
24 PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind,
25 Handle<HeapType> type, Handle<JSObject> holder,
26 CacheHolderFlag cache_holder)
27 : PropertyAccessCompiler(isolate, kind, cache_holder),
31 virtual ~PropertyHandlerCompiler() {}
33 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
39 virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
41 Register Frontend(Register object_reg, Handle<Name> name);
42 void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
43 Register scratch1, Register scratch2);
45 // TODO(verwaest): Make non-static.
46 static void GenerateFastApiCall(MacroAssembler* masm,
47 const CallOptimization& optimization,
48 Handle<Map> receiver_map, Register receiver,
49 Register scratch, bool is_store, int argc,
52 // Helper function used to check that the dictionary doesn't contain
53 // the property. This function may return false negatives, so miss_label
54 // must always call a backup property check that is complete.
55 // This function is safe to call if the receiver has fast properties.
56 // Name must be unique and receiver must be a heap object.
57 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
60 Handle<Name> name, Register r0,
63 // Generate code to check that a global property cell is empty. Create
64 // the property cell at compilation time if no cell exists for the
66 static void GenerateCheckPropertyCell(MacroAssembler* masm,
67 Handle<JSGlobalObject> global,
68 Handle<Name> name, Register scratch,
71 // Generates code that verifies that the property holder has not changed
72 // (checking maps of objects in the prototype chain for fast and global
73 // objects or doing negative lookup for slow objects, ensures that the
74 // property cells for global objects are still empty) and checks that the map
75 // of the holder has not changed. If necessary the function also generates
76 // code for security check in case of global object holders. Helps to make
77 // sure that the current IC is still valid.
79 // The scratch and holder registers are always clobbered, but the object
80 // register is only clobbered if it the same as the holder register. The
81 // function returns a register containing the holder - either object_reg or
83 Register CheckPrototypes(Register object_reg, Register holder_reg,
84 Register scratch1, Register scratch2,
85 Handle<Name> name, Label* miss,
86 PrototypeCheckType check = CHECK_ALL_MAPS);
88 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name);
89 void set_type_for_object(Handle<Object> object);
90 void set_holder(Handle<JSObject> holder) { holder_ = holder; }
91 Handle<HeapType> type() const { return type_; }
92 Handle<JSObject> holder() const { return holder_; }
95 Handle<HeapType> type_;
96 Handle<JSObject> holder_;
100 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
102 NamedLoadHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
103 Handle<JSObject> holder,
104 CacheHolderFlag cache_holder)
105 : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, holder,
108 virtual ~NamedLoadHandlerCompiler() {}
110 Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index);
112 Handle<Code> CompileLoadCallback(Handle<Name> name,
113 Handle<ExecutableAccessorInfo> callback);
115 Handle<Code> CompileLoadCallback(Handle<Name> name,
116 const CallOptimization& call_optimization);
118 Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index);
120 // The LookupIterator is used to perform a lookup behind the interceptor. If
121 // the iterator points to a LookupIterator::PROPERTY, its access will be
123 Handle<Code> CompileLoadInterceptor(LookupIterator* it);
125 Handle<Code> CompileLoadViaGetter(Handle<Name> name,
126 Handle<JSFunction> getter);
128 Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
129 bool is_configurable);
132 static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
133 Handle<HeapType> type);
135 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type,
137 Handle<JSFunction> getter);
139 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
140 GenerateLoadViaGetter(masm, Handle<HeapType>::null(), no_reg,
141 Handle<JSFunction>());
144 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
150 // These constants describe the structure of the interceptor arguments on the
151 // stack. The arguments are pushed by the (platform-specific)
152 // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
153 // LoadWithInterceptor.
154 static const int kInterceptorArgsNameIndex = 0;
155 static const int kInterceptorArgsInfoIndex = 1;
156 static const int kInterceptorArgsThisIndex = 2;
157 static const int kInterceptorArgsHolderIndex = 3;
158 static const int kInterceptorArgsLength = 4;
161 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
164 virtual void FrontendFooter(Handle<Name> name, Label* miss);
167 Handle<Code> CompileLoadNonexistent(Handle<Name> name);
168 void GenerateLoadConstant(Handle<Object> value);
169 void GenerateLoadCallback(Register reg,
170 Handle<ExecutableAccessorInfo> callback);
171 void GenerateLoadCallback(const CallOptimization& call_optimization,
172 Handle<Map> receiver_map);
173 void GenerateLoadInterceptor(Register holder_reg);
174 void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
175 Register holder_reg);
176 void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
178 // Generates prototype loading code that uses the objects from the
179 // context we were in when this function was called. If the context
180 // has changed, a jump to miss is performed. This ties the generated
181 // code to a particular context and so must not be used in cases
182 // where the generated code is not allowed to have references to
183 // objects from a context.
184 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
190 Register scratch4() { return registers_[5]; }
194 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
196 explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
197 Handle<JSObject> holder)
198 : PropertyHandlerCompiler(isolate, Code::STORE_IC, type, holder,
201 virtual ~NamedStoreHandlerCompiler() {}
203 Handle<Code> CompileStoreTransition(Handle<Map> transition,
205 Handle<Code> CompileStoreField(LookupIterator* it);
206 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
207 Handle<ExecutableAccessorInfo> callback);
208 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
209 const CallOptimization& call_optimization);
210 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
211 Handle<JSFunction> setter);
212 Handle<Code> CompileStoreInterceptor(Handle<Name> name);
214 static void GenerateStoreViaSetter(MacroAssembler* masm,
215 Handle<HeapType> type, Register receiver,
216 Handle<JSFunction> setter);
218 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
219 GenerateStoreViaSetter(masm, Handle<HeapType>::null(), no_reg,
220 Handle<JSFunction>());
223 static void GenerateSlow(MacroAssembler* masm);
226 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
229 virtual void FrontendFooter(Handle<Name> name, Label* miss);
230 void GenerateRestoreName(Label* label, Handle<Name> name);
233 void GenerateStoreTransition(Handle<Map> transition, Handle<Name> name,
234 Register receiver_reg, Register name_reg,
235 Register value_reg, Register scratch1,
236 Register scratch2, Register scratch3,
237 Label* miss_label, Label* slow);
239 void GenerateStoreField(LookupIterator* lookup, Register value_reg,
242 static Builtins::Name SlowBuiltin(Code::Kind kind) {
245 return Builtins::kStoreIC_Slow;
246 case Code::KEYED_STORE_IC:
247 return Builtins::kKeyedStoreIC_Slow;
251 return Builtins::kStoreIC_Slow;
254 static Register value();
258 class ElementHandlerCompiler : public PropertyHandlerCompiler {
260 explicit ElementHandlerCompiler(Isolate* isolate)
261 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
262 Handle<HeapType>::null(),
263 Handle<JSObject>::null(), kCacheOnReceiver) {}
265 virtual ~ElementHandlerCompiler() {}
267 void CompileElementHandlers(MapHandleList* receiver_maps,
268 CodeHandleList* handlers);
270 static void GenerateStoreSlow(MacroAssembler* masm);
273 } // namespace v8::internal
275 #endif // V8_IC_HANDLER_COMPILER_H_