blob: fcf1ec0914471c0f99b6c08f082b7daa81010bf4 [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
272 // Clear the use of the inlined version.
273 static void ClearInlinedVersion(Address address);
274
275 private:
276 static void Generate(MacroAssembler* masm, const ExternalReference& f);
277
278 // Update the inline cache.
279 void UpdateCaches(LookupResult* lookup,
280 State state,
281 Handle<Object> object,
282 Handle<String> name);
283
284 // Stub accessors.
285 static Code* initialize_stub() {
286 return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
287 }
288 static Code* megamorphic_stub() {
289 return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
290 }
291 static Code* generic_stub() {
292 return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
293 }
294 static Code* pre_monomorphic_stub() {
295 return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
296 }
297
298 static void Clear(Address address, Code* target);
299
300 // Support for patching the map that is checked in an inlined
301 // version of keyed load.
302 static bool PatchInlinedLoad(Address address, Object* map);
303
304 friend class IC;
305};
306
307
308class StoreIC: public IC {
309 public:
310 StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
311
312 Object* Store(State state,
313 Handle<Object> object,
314 Handle<String> name,
315 Handle<Object> value);
316
317 // Code generators for stub routines. Only called once at startup.
318 static void GenerateInitialize(MacroAssembler* masm);
319 static void GenerateMiss(MacroAssembler* masm);
320 static void GenerateMegamorphic(MacroAssembler* masm);
321 static void GenerateExtendStorage(MacroAssembler* masm);
322
323 private:
324 static void Generate(MacroAssembler* masm, const ExternalReference& f);
325
326 // Update the inline cache and the global stub cache based on the
327 // lookup result.
328 void UpdateCaches(LookupResult* lookup,
329 State state, Handle<JSObject> receiver,
330 Handle<String> name,
331 Handle<Object> value);
332
333 // Stub accessors.
334 static Code* megamorphic_stub() {
335 return Builtins::builtin(Builtins::StoreIC_Megamorphic);
336 }
337 static Code* initialize_stub() {
338 return Builtins::builtin(Builtins::StoreIC_Initialize);
339 }
340
341 static void Clear(Address address, Code* target);
342 friend class IC;
343};
344
345
346class KeyedStoreIC: public IC {
347 public:
348 KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
349
350 Object* Store(State state,
351 Handle<Object> object,
352 Handle<Object> name,
353 Handle<Object> value);
354
355 // Code generators for stub routines. Only called once at startup.
356 static void GenerateInitialize(MacroAssembler* masm);
357 static void GenerateMiss(MacroAssembler* masm);
358 static void GenerateGeneric(MacroAssembler* masm);
359 static void GenerateExtendStorage(MacroAssembler* masm);
360
361 // Clear the inlined version so the IC is always hit.
362 static void ClearInlinedVersion(Address address);
363
364 // Restore the inlined version so the fast case can get hit.
365 static void RestoreInlinedVersion(Address address);
366
367 private:
368 static void Generate(MacroAssembler* masm, const ExternalReference& f);
369
370 // Update the inline cache.
371 void UpdateCaches(LookupResult* lookup,
372 State state,
373 Handle<JSObject> receiver,
374 Handle<String> name,
375 Handle<Object> value);
376
377 // Stub accessors.
378 static Code* initialize_stub() {
379 return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
380 }
381 static Code* megamorphic_stub() {
382 return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
383 }
384 static Code* generic_stub() {
385 return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
386 }
387
388 static void Clear(Address address, Code* target);
389
390 // Support for patching the map that is checked in an inlined
391 // version of keyed store.
392 // The address is the patch point for the IC call
393 // (Assembler::kCallTargetAddressOffset before the end of
394 // the call/return address).
395 // The map is the new map that the inlined code should check against.
396 static bool PatchInlinedStore(Address address, Object* map);
397
398 friend class IC;
399};
400
401
402} } // namespace v8::internal
403
404#endif // V8_IC_H_