blob: 870908838b18ba1642db3b2000c8ad601fe1ee7f [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_IC_H_
29#define V8_IC_H_
30
31#include "assembler.h"
32
33namespace v8 {
34namespace internal {
35
36// IC_UTIL_LIST defines all utility functions called from generated
37// inline caching code. The argument for the macro, ICU, is the function name.
38#define IC_UTIL_LIST(ICU) \
39 ICU(LoadIC_Miss) \
40 ICU(KeyedLoadIC_Miss) \
41 ICU(CallIC_Miss) \
42 ICU(StoreIC_Miss) \
43 ICU(SharedStoreIC_ExtendStorage) \
44 ICU(KeyedStoreIC_Miss) \
45 /* Utilities for IC stubs. */ \
46 ICU(LoadCallbackProperty) \
47 ICU(StoreCallbackProperty) \
48 ICU(LoadPropertyWithInterceptorOnly) \
49 ICU(LoadPropertyWithInterceptorForLoad) \
50 ICU(LoadPropertyWithInterceptorForCall) \
51 ICU(StoreInterceptorProperty)
52
53//
54// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
55// and KeyedStoreIC.
56//
57class IC {
58 public:
59
60 // The ids for utility called from the generated code.
61 enum UtilityId {
62 #define CONST_NAME(name) k##name,
63 IC_UTIL_LIST(CONST_NAME)
64 #undef CONST_NAME
65 kUtilityCount
66 };
67
68 // Looks up the address of the named utility.
69 static Address AddressFromUtilityId(UtilityId id);
70
71 // Alias the inline cache state type to make the IC code more readable.
72 typedef InlineCacheState State;
73
74 // The IC code is either invoked with no extra frames on the stack
75 // or with a single extra frame for supporting calls.
76 enum FrameDepth {
77 NO_EXTRA_FRAME = 0,
78 EXTRA_CALL_FRAME = 1
79 };
80
81 // Construct the IC structure with the given number of extra
82 // JavaScript frames on the stack.
83 explicit IC(FrameDepth depth);
84
85 // Get the call-site target; used for determining the state.
86 Code* target() { return GetTargetAtAddress(address()); }
87 inline Address address();
88
89 // Compute the current IC state based on the target stub and the receiver.
90 static State StateFrom(Code* target, Object* receiver);
91
92 // Clear the inline cache to initial state.
93 static void Clear(Address address);
94
95 // Computes the reloc info for this IC. This is a fairly expensive
96 // operation as it has to search through the heap to find the code
97 // object that contains this IC site.
98 RelocInfo::Mode ComputeMode();
99
100 // Returns if this IC is for contextual (no explicit receiver)
101 // access to properties.
102 bool is_contextual() {
103 return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
104 }
105
106 // Returns the map to use for caching stubs for a given object.
107 // This method should not be called with undefined or null.
108 static inline Map* GetCodeCacheMapForObject(Object* object);
109
110 protected:
111 Address fp() const { return fp_; }
112 Address pc() const { return *pc_address_; }
113
114#ifdef ENABLE_DEBUGGER_SUPPORT
115 // Computes the address in the original code when the code running is
116 // containing break points (calls to DebugBreakXXX builtins).
117 Address OriginalCodeAddress();
118#endif
119
120 // Set the call-site target.
121 void set_target(Code* code) { SetTargetAtAddress(address(), code); }
122
123#ifdef DEBUG
124 static void TraceIC(const char* type,
125 Handle<String> name,
126 State old_state,
127 Code* new_target,
128 const char* extra_info = "");
129#endif
130
131 static Failure* TypeError(const char* type,
132 Handle<Object> object,
133 Handle<String> name);
134 static Failure* ReferenceError(const char* type, Handle<String> name);
135
136 // Access the target code for the given IC address.
137 static inline Code* GetTargetAtAddress(Address address);
138 static inline void SetTargetAtAddress(Address address, Code* target);
139
140 private:
141 // Frame pointer for the frame that uses (calls) the IC.
142 Address fp_;
143
144 // All access to the program counter of an IC structure is indirect
145 // to make the code GC safe. This feature is crucial since
146 // GetProperty and SetProperty are called and they in turn might
147 // invoke the garbage collector.
148 Address* pc_address_;
149
150 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
151};
152
153
154// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
155// cannot make forward declarations to an enum.
156class IC_Utility {
157 public:
158 explicit IC_Utility(IC::UtilityId id)
159 : address_(IC::AddressFromUtilityId(id)), id_(id) {}
160
161 Address address() const { return address_; }
162
163 IC::UtilityId id() const { return id_; }
164 private:
165 Address address_;
166 IC::UtilityId id_;
167};
168
169
170class CallIC: public IC {
171 public:
172 CallIC() : IC(EXTRA_CALL_FRAME) { ASSERT(target()->is_call_stub()); }
173
174 Object* LoadFunction(State state, Handle<Object> object, Handle<String> name);
175
176
177 // Code generator routines.
178 static void GenerateInitialize(MacroAssembler* masm, int argc);
179 static void GenerateMiss(MacroAssembler* masm, int argc);
180 static void GenerateMegamorphic(MacroAssembler* masm, int argc);
181 static void GenerateNormal(MacroAssembler* masm, int argc);
182
183 private:
184 static void Generate(MacroAssembler* masm,
185 int argc,
186 const ExternalReference& f);
187
188 // Update the inline cache and the global stub cache based on the
189 // lookup result.
190 void UpdateCaches(LookupResult* lookup,
191 State state,
192 Handle<Object> object,
193 Handle<String> name);
194
195 // Returns a JSFunction if the object can be called as a function,
196 // and patches the stack to be ready for the call.
197 // Otherwise, it returns the undefined value.
198 Object* TryCallAsFunction(Object* object);
199
200 static void Clear(Address address, Code* target);
201 friend class IC;
202};
203
204
205class LoadIC: public IC {
206 public:
207 LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
208
209 Object* Load(State state, Handle<Object> object, Handle<String> name);
210
211 // Code generator routines.
212 static void GenerateInitialize(MacroAssembler* masm);
213 static void GeneratePreMonomorphic(MacroAssembler* masm);
214 static void GenerateMiss(MacroAssembler* masm);
215 static void GenerateMegamorphic(MacroAssembler* masm);
216 static void GenerateNormal(MacroAssembler* masm);
217
218 // Specialized code generator routines.
219 static void GenerateArrayLength(MacroAssembler* masm);
220 static void GenerateStringLength(MacroAssembler* masm);
221 static void GenerateFunctionPrototype(MacroAssembler* masm);
222
223 // The offset from the inlined patch site to the start of the
224 // inlined load instruction. It is architecture-dependent, and not
225 // used on ARM.
226 static const int kOffsetToLoadInstruction;
227
228 private:
229 static void Generate(MacroAssembler* masm, const ExternalReference& f);
230
231 // Update the inline cache and the global stub cache based on the
232 // lookup result.
233 void UpdateCaches(LookupResult* lookup,
234 State state,
235 Handle<Object> object,
236 Handle<String> name);
237
238 // Stub accessors.
239 static Code* megamorphic_stub() {
240 return Builtins::builtin(Builtins::LoadIC_Megamorphic);
241 }
242 static Code* initialize_stub() {
243 return Builtins::builtin(Builtins::LoadIC_Initialize);
244 }
245 static Code* pre_monomorphic_stub() {
246 return Builtins::builtin(Builtins::LoadIC_PreMonomorphic);
247 }
248
249 static void Clear(Address address, Code* target);
250
251 // Clear the use of the inlined version.
252 static void ClearInlinedVersion(Address address);
253
254 static bool PatchInlinedLoad(Address address, Object* map, int index);
255
256 friend class IC;
257};
258
259
260class KeyedLoadIC: public IC {
261 public:
262 KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
263
264 Object* Load(State state, Handle<Object> object, Handle<Object> key);
265
266 // Code generator routines.
267 static void GenerateMiss(MacroAssembler* masm);
268 static void GenerateInitialize(MacroAssembler* masm);
269 static void GeneratePreMonomorphic(MacroAssembler* masm);
270 static void GenerateGeneric(MacroAssembler* masm);
271
Steve Block3ce2e202009-11-05 08:53:23 +0000272 // Generators for external array types. See objects.h.
273 // These are similar to the generic IC; they optimize the case of
274 // operating upon external array types but fall back to the runtime
275 // for all other types.
276 static void GenerateExternalArray(MacroAssembler* masm,
277 ExternalArrayType array_type);
278
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 // Clear the use of the inlined version.
280 static void ClearInlinedVersion(Address address);
281
282 private:
283 static void Generate(MacroAssembler* masm, const ExternalReference& f);
284
285 // Update the inline cache.
286 void UpdateCaches(LookupResult* lookup,
287 State state,
288 Handle<Object> object,
289 Handle<String> name);
290
291 // Stub accessors.
292 static Code* initialize_stub() {
293 return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
294 }
295 static Code* megamorphic_stub() {
296 return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
297 }
298 static Code* generic_stub() {
299 return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
300 }
301 static Code* pre_monomorphic_stub() {
302 return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
303 }
Steve Block3ce2e202009-11-05 08:53:23 +0000304 static Code* external_array_stub(JSObject::ElementsKind elements_kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
306 static void Clear(Address address, Code* target);
307
308 // Support for patching the map that is checked in an inlined
309 // version of keyed load.
310 static bool PatchInlinedLoad(Address address, Object* map);
311
312 friend class IC;
313};
314
315
316class StoreIC: public IC {
317 public:
318 StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
319
320 Object* Store(State state,
321 Handle<Object> object,
322 Handle<String> name,
323 Handle<Object> value);
324
325 // Code generators for stub routines. Only called once at startup.
326 static void GenerateInitialize(MacroAssembler* masm);
327 static void GenerateMiss(MacroAssembler* masm);
328 static void GenerateMegamorphic(MacroAssembler* masm);
329 static void GenerateExtendStorage(MacroAssembler* masm);
330
331 private:
332 static void Generate(MacroAssembler* masm, const ExternalReference& f);
333
334 // Update the inline cache and the global stub cache based on the
335 // lookup result.
336 void UpdateCaches(LookupResult* lookup,
337 State state, Handle<JSObject> receiver,
338 Handle<String> name,
339 Handle<Object> value);
340
341 // Stub accessors.
342 static Code* megamorphic_stub() {
343 return Builtins::builtin(Builtins::StoreIC_Megamorphic);
344 }
345 static Code* initialize_stub() {
346 return Builtins::builtin(Builtins::StoreIC_Initialize);
347 }
348
349 static void Clear(Address address, Code* target);
350 friend class IC;
351};
352
353
354class KeyedStoreIC: public IC {
355 public:
356 KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
357
358 Object* Store(State state,
359 Handle<Object> object,
360 Handle<Object> name,
361 Handle<Object> value);
362
363 // Code generators for stub routines. Only called once at startup.
364 static void GenerateInitialize(MacroAssembler* masm);
365 static void GenerateMiss(MacroAssembler* masm);
366 static void GenerateGeneric(MacroAssembler* masm);
367 static void GenerateExtendStorage(MacroAssembler* masm);
368
Steve Block3ce2e202009-11-05 08:53:23 +0000369 // Generators for external array types. See objects.h.
370 // These are similar to the generic IC; they optimize the case of
371 // operating upon external array types but fall back to the runtime
372 // for all other types.
373 static void GenerateExternalArray(MacroAssembler* masm,
374 ExternalArrayType array_type);
375
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 // Clear the inlined version so the IC is always hit.
377 static void ClearInlinedVersion(Address address);
378
379 // Restore the inlined version so the fast case can get hit.
380 static void RestoreInlinedVersion(Address address);
381
382 private:
383 static void Generate(MacroAssembler* masm, const ExternalReference& f);
384
385 // Update the inline cache.
386 void UpdateCaches(LookupResult* lookup,
387 State state,
388 Handle<JSObject> receiver,
389 Handle<String> name,
390 Handle<Object> value);
391
392 // Stub accessors.
393 static Code* initialize_stub() {
394 return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
395 }
396 static Code* megamorphic_stub() {
397 return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
398 }
399 static Code* generic_stub() {
400 return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
401 }
Steve Block3ce2e202009-11-05 08:53:23 +0000402 static Code* external_array_stub(JSObject::ElementsKind elements_kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000403
404 static void Clear(Address address, Code* target);
405
406 // Support for patching the map that is checked in an inlined
407 // version of keyed store.
408 // The address is the patch point for the IC call
409 // (Assembler::kCallTargetAddressOffset before the end of
410 // the call/return address).
411 // The map is the new map that the inlined code should check against.
412 static bool PatchInlinedStore(Address address, Object* map);
413
414 friend class IC;
415};
416
417
418} } // namespace v8::internal
419
420#endif // V8_IC_H_