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 };
17 enum ReturnHolder { RETURN_HOLDER, DONT_RETURN_ANYTHING };
19 class PropertyHandlerCompiler : public PropertyAccessCompiler {
21 static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
22 CacheHolderFlag cache_holder, Code::StubType type);
25 PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
26 Handle<JSObject> holder, CacheHolderFlag cache_holder)
27 : PropertyAccessCompiler(isolate, kind, cache_holder),
31 virtual ~PropertyHandlerCompiler() {}
33 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
34 Label* miss, ReturnHolder return_what) {
39 virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
41 // Frontend loads from receiver(), returns holder register which may be
43 Register Frontend(Handle<Name> name);
44 void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
45 Register scratch1, Register scratch2);
47 // When FLAG_vector_ics is true, handlers that have the possibility of missing
48 // will need to save and pass these to miss handlers.
49 void PushVectorAndSlot() { PushVectorAndSlot(vector(), slot()); }
50 void PushVectorAndSlot(Register vector, Register slot);
51 void PopVectorAndSlot() { PopVectorAndSlot(vector(), slot()); }
52 void PopVectorAndSlot(Register vector, Register slot);
54 void DiscardVectorAndSlot();
56 // TODO(verwaest): Make non-static.
57 static void GenerateApiAccessorCall(MacroAssembler* masm,
58 const CallOptimization& optimization,
59 Handle<Map> receiver_map,
60 Register receiver, Register scratch,
61 bool is_store, Register store_parameter,
62 Register accessor_holder,
65 // Helper function used to check that the dictionary doesn't contain
66 // the property. This function may return false negatives, so miss_label
67 // must always call a backup property check that is complete.
68 // This function is safe to call if the receiver has fast properties.
69 // Name must be unique and receiver must be a heap object.
70 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
73 Handle<Name> name, Register r0,
76 // Generate code to check that a global property cell is empty. Create
77 // the property cell at compilation time if no cell exists for the
79 static void GenerateCheckPropertyCell(MacroAssembler* masm,
80 Handle<JSGlobalObject> global,
81 Handle<Name> name, Register scratch,
84 // Generates code that verifies that the property holder has not changed
85 // (checking maps of objects in the prototype chain for fast and global
86 // objects or doing negative lookup for slow objects, ensures that the
87 // property cells for global objects are still empty) and checks that the map
88 // of the holder has not changed. If necessary the function also generates
89 // code for security check in case of global object holders. Helps to make
90 // sure that the current IC is still valid.
92 // The scratch and holder registers are always clobbered, but the object
93 // register is only clobbered if it the same as the holder register. The
94 // function returns a register containing the holder - either object_reg or
96 Register CheckPrototypes(Register object_reg, Register holder_reg,
97 Register scratch1, Register scratch2,
98 Handle<Name> name, Label* miss,
99 PrototypeCheckType check, ReturnHolder return_what);
101 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name);
102 void set_holder(Handle<JSObject> holder) { holder_ = holder; }
103 Handle<Map> map() const { return map_; }
104 void set_map(Handle<Map> map) { map_ = map; }
105 Handle<JSObject> holder() const { return holder_; }
109 Handle<JSObject> holder_;
113 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
115 NamedLoadHandlerCompiler(Isolate* isolate, Handle<Map> map,
116 Handle<JSObject> holder,
117 CacheHolderFlag cache_holder)
118 : PropertyHandlerCompiler(isolate, Code::LOAD_IC, map, holder,
121 virtual ~NamedLoadHandlerCompiler() {}
123 Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index);
125 Handle<Code> CompileLoadCallback(Handle<Name> name,
126 Handle<ExecutableAccessorInfo> callback);
128 Handle<Code> CompileLoadCallback(Handle<Name> name,
129 const CallOptimization& call_optimization,
132 Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index);
134 // The LookupIterator is used to perform a lookup behind the interceptor. If
135 // the iterator points to a LookupIterator::PROPERTY, its access will be
137 Handle<Code> CompileLoadInterceptor(LookupIterator* it);
139 Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
140 int expected_arguments);
142 Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
143 bool is_configurable);
146 static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
149 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
150 Register receiver, Register holder,
151 int accessor_index, int expected_arguments,
154 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
155 GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
159 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
165 // These constants describe the structure of the interceptor arguments on the
166 // stack. The arguments are pushed by the (platform-specific)
167 // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
168 // LoadWithInterceptor.
169 static const int kInterceptorArgsNameIndex = 0;
170 static const int kInterceptorArgsThisIndex = 1;
171 static const int kInterceptorArgsHolderIndex = 2;
172 static const int kInterceptorArgsLength = 3;
175 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
176 Label* miss, ReturnHolder return_what);
178 virtual void FrontendFooter(Handle<Name> name, Label* miss);
181 Handle<Code> CompileLoadNonexistent(Handle<Name> name);
182 void GenerateLoadConstant(Handle<Object> value);
183 void GenerateLoadCallback(Register reg,
184 Handle<ExecutableAccessorInfo> callback);
185 void GenerateLoadCallback(const CallOptimization& call_optimization,
186 Handle<Map> receiver_map);
188 // Helper emits no code if vector-ics are disabled.
189 void InterceptorVectorSlotPush(Register holder_reg);
190 enum PopMode { POP, DISCARD };
191 void InterceptorVectorSlotPop(Register holder_reg, PopMode mode = POP);
193 void GenerateLoadInterceptor(Register holder_reg);
194 void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
195 Register holder_reg);
196 void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
198 // Generates prototype loading code that uses the objects from the
199 // context we were in when this function was called. If the context
200 // has changed, a jump to miss is performed. This ties the generated
201 // code to a particular context and so must not be used in cases
202 // where the generated code is not allowed to have references to
203 // objects from a context.
204 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
210 Register scratch4() { return registers_[5]; }
214 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
216 explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
217 Handle<JSObject> holder)
218 : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
221 virtual ~NamedStoreHandlerCompiler() {}
223 Handle<Code> CompileStoreTransition(Handle<Map> transition,
225 Handle<Code> CompileStoreField(LookupIterator* it);
226 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
227 Handle<ExecutableAccessorInfo> callback);
228 Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
229 const CallOptimization& call_optimization,
231 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
233 int expected_arguments);
234 Handle<Code> CompileStoreInterceptor(Handle<Name> name);
236 static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
237 Register receiver, Register holder,
238 int accessor_index, int expected_arguments,
241 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
242 GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
246 static void GenerateSlow(MacroAssembler* masm);
249 virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
250 Label* miss, ReturnHolder return_what);
252 virtual void FrontendFooter(Handle<Name> name, Label* miss);
253 void GenerateRestoreName(Label* label, Handle<Name> name);
254 void GeneratePushMap(Register map_reg, Register scratch);
257 void GenerateRestoreName(Handle<Name> name);
258 void GenerateRestoreMap(Handle<Map> transition, Register map_reg,
259 Register scratch, Label* miss);
261 void GenerateConstantCheck(Register map_reg, int descriptor,
262 Register value_reg, Register scratch,
265 bool RequiresFieldTypeChecks(HeapType* field_type) const;
266 void GenerateFieldTypeChecks(HeapType* field_type, Register value_reg,
269 static Builtins::Name SlowBuiltin(Code::Kind kind) {
272 return Builtins::kStoreIC_Slow;
273 case Code::KEYED_STORE_IC:
274 return Builtins::kKeyedStoreIC_Slow;
278 return Builtins::kStoreIC_Slow;
281 static Register value();
285 class ElementHandlerCompiler : public PropertyHandlerCompiler {
287 explicit ElementHandlerCompiler(Isolate* isolate)
288 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
289 Handle<Map>::null(), Handle<JSObject>::null(),
292 virtual ~ElementHandlerCompiler() {}
294 void CompileElementHandlers(MapHandleList* receiver_maps,
295 CodeHandleList* handlers,
296 LanguageMode language_mode);
298 static void GenerateStoreSlow(MacroAssembler* masm);
301 } // namespace v8::internal
303 #endif // V8_IC_HANDLER_COMPILER_H_