• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 #include "v8.h"
29 
30 #include "api.h"
31 #include "arguments.h"
32 #include "ic-inl.h"
33 #include "stub-cache.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 // -----------------------------------------------------------------------
39 // StubCache implementation.
40 
41 
42 StubCache::Entry StubCache::primary_[StubCache::kPrimaryTableSize];
43 StubCache::Entry StubCache::secondary_[StubCache::kSecondaryTableSize];
44 
Initialize(bool create_heap_objects)45 void StubCache::Initialize(bool create_heap_objects) {
46   ASSERT(IsPowerOf2(kPrimaryTableSize));
47   ASSERT(IsPowerOf2(kSecondaryTableSize));
48   if (create_heap_objects) {
49     HandleScope scope;
50     Clear();
51   }
52 }
53 
54 
Set(String * name,Map * map,Code * code)55 Code* StubCache::Set(String* name, Map* map, Code* code) {
56   // Get the flags from the code.
57   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
58 
59   // Validate that the name does not move on scavenge, and that we
60   // can use identity checks instead of string equality checks.
61   ASSERT(!Heap::InNewSpace(name));
62   ASSERT(name->IsSymbol());
63 
64   // The state bits are not important to the hash function because
65   // the stub cache only contains monomorphic stubs. Make sure that
66   // the bits are the least significant so they will be the ones
67   // masked out.
68   ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
69   ASSERT(Code::kFlagsICStateShift == 0);
70 
71   // Make sure that the code type is not included in the hash.
72   ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
73 
74   // Compute the primary entry.
75   int primary_offset = PrimaryOffset(name, flags, map);
76   Entry* primary = entry(primary_, primary_offset);
77   Code* hit = primary->value;
78 
79   // If the primary entry has useful data in it, we retire it to the
80   // secondary cache before overwriting it.
81   if (hit != Builtins::builtin(Builtins::Illegal)) {
82     Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
83     int secondary_offset =
84         SecondaryOffset(primary->key, primary_flags, primary_offset);
85     Entry* secondary = entry(secondary_, secondary_offset);
86     *secondary = *primary;
87   }
88 
89   // Update primary cache.
90   primary->key = name;
91   primary->value = code;
92   return code;
93 }
94 
95 
ComputeLoadField(String * name,JSObject * receiver,JSObject * holder,int field_index)96 Object* StubCache::ComputeLoadField(String* name,
97                                     JSObject* receiver,
98                                     JSObject* holder,
99                                     int field_index) {
100   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
101   Object* code = receiver->map()->FindInCodeCache(name, flags);
102   if (code->IsUndefined()) {
103     LoadStubCompiler compiler;
104     code = compiler.CompileLoadField(receiver, holder, field_index, name);
105     if (code->IsFailure()) return code;
106     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
107     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
108     if (result->IsFailure()) return code;
109   }
110   return Set(name, receiver->map(), Code::cast(code));
111 }
112 
113 
ComputeLoadCallback(String * name,JSObject * receiver,JSObject * holder,AccessorInfo * callback)114 Object* StubCache::ComputeLoadCallback(String* name,
115                                        JSObject* receiver,
116                                        JSObject* holder,
117                                        AccessorInfo* callback) {
118   ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
119   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
120   Object* code = receiver->map()->FindInCodeCache(name, flags);
121   if (code->IsUndefined()) {
122     LoadStubCompiler compiler;
123     code = compiler.CompileLoadCallback(receiver, holder, callback, name);
124     if (code->IsFailure()) return code;
125     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
126     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
127     if (result->IsFailure()) return code;
128   }
129   return Set(name, receiver->map(), Code::cast(code));
130 }
131 
132 
ComputeLoadConstant(String * name,JSObject * receiver,JSObject * holder,Object * value)133 Object* StubCache::ComputeLoadConstant(String* name,
134                                        JSObject* receiver,
135                                        JSObject* holder,
136                                        Object* value) {
137   Code::Flags flags =
138       Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
139   Object* code = receiver->map()->FindInCodeCache(name, flags);
140   if (code->IsUndefined()) {
141     LoadStubCompiler compiler;
142     code = compiler.CompileLoadConstant(receiver, holder, value, name);
143     if (code->IsFailure()) return code;
144     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
145     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
146     if (result->IsFailure()) return code;
147   }
148   return Set(name, receiver->map(), Code::cast(code));
149 }
150 
151 
ComputeLoadInterceptor(String * name,JSObject * receiver,JSObject * holder)152 Object* StubCache::ComputeLoadInterceptor(String* name,
153                                           JSObject* receiver,
154                                           JSObject* holder) {
155   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
156   Object* code = receiver->map()->FindInCodeCache(name, flags);
157   if (code->IsUndefined()) {
158     LoadStubCompiler compiler;
159     code = compiler.CompileLoadInterceptor(receiver, holder, name);
160     if (code->IsFailure()) return code;
161     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
162     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
163     if (result->IsFailure()) return code;
164   }
165   return Set(name, receiver->map(), Code::cast(code));
166 }
167 
168 
ComputeLoadNormal(String * name,JSObject * receiver)169 Object* StubCache::ComputeLoadNormal(String* name, JSObject* receiver) {
170   Code* code = Builtins::builtin(Builtins::LoadIC_Normal);
171   return Set(name, receiver->map(), code);
172 }
173 
174 
ComputeLoadGlobal(String * name,JSObject * receiver,GlobalObject * holder,JSGlobalPropertyCell * cell,bool is_dont_delete)175 Object* StubCache::ComputeLoadGlobal(String* name,
176                                      JSObject* receiver,
177                                      GlobalObject* holder,
178                                      JSGlobalPropertyCell* cell,
179                                      bool is_dont_delete) {
180   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
181   Object* code = receiver->map()->FindInCodeCache(name, flags);
182   if (code->IsUndefined()) {
183     LoadStubCompiler compiler;
184     code = compiler.CompileLoadGlobal(receiver,
185                                       holder,
186                                       cell,
187                                       name,
188                                       is_dont_delete);
189     if (code->IsFailure()) return code;
190     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
191     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
192     if (result->IsFailure()) return code;
193   }
194   return Set(name, receiver->map(), Code::cast(code));
195 }
196 
197 
ComputeKeyedLoadField(String * name,JSObject * receiver,JSObject * holder,int field_index)198 Object* StubCache::ComputeKeyedLoadField(String* name,
199                                          JSObject* receiver,
200                                          JSObject* holder,
201                                          int field_index) {
202   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
203   Object* code = receiver->map()->FindInCodeCache(name, flags);
204   if (code->IsUndefined()) {
205     KeyedLoadStubCompiler compiler;
206     code = compiler.CompileLoadField(name, receiver, holder, field_index);
207     if (code->IsFailure()) return code;
208     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
209     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
210     if (result->IsFailure()) return result;
211   }
212   return code;
213 }
214 
215 
ComputeKeyedLoadConstant(String * name,JSObject * receiver,JSObject * holder,Object * value)216 Object* StubCache::ComputeKeyedLoadConstant(String* name,
217                                             JSObject* receiver,
218                                             JSObject* holder,
219                                             Object* value) {
220   Code::Flags flags =
221       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
222   Object* code = receiver->map()->FindInCodeCache(name, flags);
223   if (code->IsUndefined()) {
224     KeyedLoadStubCompiler compiler;
225     code = compiler.CompileLoadConstant(name, receiver, holder, value);
226     if (code->IsFailure()) return code;
227     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
228     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
229     if (result->IsFailure()) return result;
230   }
231   return code;
232 }
233 
234 
ComputeKeyedLoadInterceptor(String * name,JSObject * receiver,JSObject * holder)235 Object* StubCache::ComputeKeyedLoadInterceptor(String* name,
236                                                JSObject* receiver,
237                                                JSObject* holder) {
238   Code::Flags flags =
239       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
240   Object* code = receiver->map()->FindInCodeCache(name, flags);
241   if (code->IsUndefined()) {
242     KeyedLoadStubCompiler compiler;
243     code = compiler.CompileLoadInterceptor(receiver, holder, name);
244     if (code->IsFailure()) return code;
245     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
246     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
247     if (result->IsFailure()) return result;
248   }
249   return code;
250 }
251 
252 
ComputeKeyedLoadCallback(String * name,JSObject * receiver,JSObject * holder,AccessorInfo * callback)253 Object* StubCache::ComputeKeyedLoadCallback(String* name,
254                                             JSObject* receiver,
255                                             JSObject* holder,
256                                             AccessorInfo* callback) {
257   Code::Flags flags =
258       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
259   Object* code = receiver->map()->FindInCodeCache(name, flags);
260   if (code->IsUndefined()) {
261     KeyedLoadStubCompiler compiler;
262     code = compiler.CompileLoadCallback(name, receiver, holder, callback);
263     if (code->IsFailure()) return code;
264     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
265     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
266     if (result->IsFailure()) return result;
267   }
268   return code;
269 }
270 
271 
272 
ComputeKeyedLoadArrayLength(String * name,JSArray * receiver)273 Object* StubCache::ComputeKeyedLoadArrayLength(String* name,
274                                                JSArray* receiver) {
275   Code::Flags flags =
276       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
277   Object* code = receiver->map()->FindInCodeCache(name, flags);
278   if (code->IsUndefined()) {
279     KeyedLoadStubCompiler compiler;
280     code = compiler.CompileLoadArrayLength(name);
281     if (code->IsFailure()) return code;
282     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
283     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
284     if (result->IsFailure()) return result;
285   }
286   return code;
287 }
288 
289 
ComputeKeyedLoadStringLength(String * name,String * receiver)290 Object* StubCache::ComputeKeyedLoadStringLength(String* name,
291                                                 String* receiver) {
292   Code::Flags flags =
293       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
294   Object* code = receiver->map()->FindInCodeCache(name, flags);
295   if (code->IsUndefined()) {
296     KeyedLoadStubCompiler compiler;
297     code = compiler.CompileLoadStringLength(name);
298     if (code->IsFailure()) return code;
299     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
300     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
301     if (result->IsFailure()) return result;
302   }
303   return code;
304 }
305 
306 
ComputeKeyedLoadFunctionPrototype(String * name,JSFunction * receiver)307 Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name,
308                                                      JSFunction* receiver) {
309   Code::Flags flags =
310       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
311   Object* code = receiver->map()->FindInCodeCache(name, flags);
312   if (code->IsUndefined()) {
313     KeyedLoadStubCompiler compiler;
314     code = compiler.CompileLoadFunctionPrototype(name);
315     if (code->IsFailure()) return code;
316     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
317     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
318     if (result->IsFailure()) return result;
319   }
320   return code;
321 }
322 
323 
ComputeStoreField(String * name,JSObject * receiver,int field_index,Map * transition)324 Object* StubCache::ComputeStoreField(String* name,
325                                      JSObject* receiver,
326                                      int field_index,
327                                      Map* transition) {
328   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
329   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
330   Object* code = receiver->map()->FindInCodeCache(name, flags);
331   if (code->IsUndefined()) {
332     StoreStubCompiler compiler;
333     code = compiler.CompileStoreField(receiver, field_index, transition, name);
334     if (code->IsFailure()) return code;
335     LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
336     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
337     if (result->IsFailure()) return result;
338   }
339   return Set(name, receiver->map(), Code::cast(code));
340 }
341 
342 
ComputeStoreGlobal(String * name,GlobalObject * receiver,JSGlobalPropertyCell * cell)343 Object* StubCache::ComputeStoreGlobal(String* name,
344                                       GlobalObject* receiver,
345                                       JSGlobalPropertyCell* cell) {
346   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
347   Object* code = receiver->map()->FindInCodeCache(name, flags);
348   if (code->IsUndefined()) {
349     StoreStubCompiler compiler;
350     code = compiler.CompileStoreGlobal(receiver, cell, name);
351     if (code->IsFailure()) return code;
352     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
353     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
354     if (result->IsFailure()) return code;
355   }
356   return Set(name, receiver->map(), Code::cast(code));
357 }
358 
359 
ComputeStoreCallback(String * name,JSObject * receiver,AccessorInfo * callback)360 Object* StubCache::ComputeStoreCallback(String* name,
361                                         JSObject* receiver,
362                                         AccessorInfo* callback) {
363   ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
364   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, CALLBACKS);
365   Object* code = receiver->map()->FindInCodeCache(name, flags);
366   if (code->IsUndefined()) {
367     StoreStubCompiler compiler;
368     code = compiler.CompileStoreCallback(receiver, callback, name);
369     if (code->IsFailure()) return code;
370     LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
371     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
372     if (result->IsFailure()) return result;
373   }
374   return Set(name, receiver->map(), Code::cast(code));
375 }
376 
377 
ComputeStoreInterceptor(String * name,JSObject * receiver)378 Object* StubCache::ComputeStoreInterceptor(String* name,
379                                            JSObject* receiver) {
380   Code::Flags flags =
381       Code::ComputeMonomorphicFlags(Code::STORE_IC, INTERCEPTOR);
382   Object* code = receiver->map()->FindInCodeCache(name, flags);
383   if (code->IsUndefined()) {
384     StoreStubCompiler compiler;
385     code = compiler.CompileStoreInterceptor(receiver, name);
386     if (code->IsFailure()) return code;
387     LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
388     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
389     if (result->IsFailure()) return result;
390   }
391   return Set(name, receiver->map(), Code::cast(code));
392 }
393 
394 
ComputeKeyedStoreField(String * name,JSObject * receiver,int field_index,Map * transition)395 Object* StubCache::ComputeKeyedStoreField(String* name, JSObject* receiver,
396                                           int field_index, Map* transition) {
397   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
398   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
399   Object* code = receiver->map()->FindInCodeCache(name, flags);
400   if (code->IsUndefined()) {
401     KeyedStoreStubCompiler compiler;
402     code = compiler.CompileStoreField(receiver, field_index, transition, name);
403     if (code->IsFailure()) return code;
404     LOG(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), name));
405     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
406     if (result->IsFailure()) return result;
407   }
408   return code;
409 }
410 
411 
ComputeCallConstant(int argc,InLoopFlag in_loop,String * name,Object * object,JSObject * holder,JSFunction * function)412 Object* StubCache::ComputeCallConstant(int argc,
413                                        InLoopFlag in_loop,
414                                        String* name,
415                                        Object* object,
416                                        JSObject* holder,
417                                        JSFunction* function) {
418   // Compute the check type and the map.
419   Map* map = IC::GetCodeCacheMapForObject(object);
420 
421   // Compute check type based on receiver/holder.
422   StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK;
423   if (object->IsString()) {
424     check = StubCompiler::STRING_CHECK;
425   } else if (object->IsNumber()) {
426     check = StubCompiler::NUMBER_CHECK;
427   } else if (object->IsBoolean()) {
428     check = StubCompiler::BOOLEAN_CHECK;
429   }
430 
431   Code::Flags flags =
432       Code::ComputeMonomorphicFlags(Code::CALL_IC,
433                                     CONSTANT_FUNCTION,
434                                     in_loop,
435                                     argc);
436   Object* code = map->FindInCodeCache(name, flags);
437   if (code->IsUndefined()) {
438     if (object->IsJSObject()) {
439       Object* opt =
440           Top::LookupSpecialFunction(JSObject::cast(object), holder, function);
441       if (opt->IsJSFunction()) {
442         check = StubCompiler::JSARRAY_HAS_FAST_ELEMENTS_CHECK;
443         function = JSFunction::cast(opt);
444       }
445     }
446     // If the function hasn't been compiled yet, we cannot do it now
447     // because it may cause GC. To avoid this issue, we return an
448     // internal error which will make sure we do not update any
449     // caches.
450     if (!function->is_compiled()) return Failure::InternalError();
451     // Compile the stub - only create stubs for fully compiled functions.
452     CallStubCompiler compiler(argc, in_loop);
453     code = compiler.CompileCallConstant(object, holder, function, name, check);
454     if (code->IsFailure()) return code;
455     ASSERT_EQ(flags, Code::cast(code)->flags());
456     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
457     Object* result = map->UpdateCodeCache(name, Code::cast(code));
458     if (result->IsFailure()) return result;
459   }
460   return Set(name, map, Code::cast(code));
461 }
462 
463 
ComputeCallField(int argc,InLoopFlag in_loop,String * name,Object * object,JSObject * holder,int index)464 Object* StubCache::ComputeCallField(int argc,
465                                     InLoopFlag in_loop,
466                                     String* name,
467                                     Object* object,
468                                     JSObject* holder,
469                                     int index) {
470   // Compute the check type and the map.
471   Map* map = IC::GetCodeCacheMapForObject(object);
472 
473   // TODO(1233596): We cannot do receiver map check for non-JS objects
474   // because they may be represented as immediates without a
475   // map. Instead, we check against the map in the holder.
476   if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
477     object = holder;
478   }
479 
480   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
481                                                     FIELD,
482                                                     in_loop,
483                                                     argc);
484   Object* code = map->FindInCodeCache(name, flags);
485   if (code->IsUndefined()) {
486     CallStubCompiler compiler(argc, in_loop);
487     code = compiler.CompileCallField(object, holder, index, name);
488     if (code->IsFailure()) return code;
489     ASSERT_EQ(flags, Code::cast(code)->flags());
490     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
491     Object* result = map->UpdateCodeCache(name, Code::cast(code));
492     if (result->IsFailure()) return result;
493   }
494   return Set(name, map, Code::cast(code));
495 }
496 
497 
ComputeCallInterceptor(int argc,String * name,Object * object,JSObject * holder)498 Object* StubCache::ComputeCallInterceptor(int argc,
499                                           String* name,
500                                           Object* object,
501                                           JSObject* holder) {
502   // Compute the check type and the map.
503   // If the object is a value, we use the prototype map for the cache.
504   Map* map = IC::GetCodeCacheMapForObject(object);
505 
506   // TODO(1233596): We cannot do receiver map check for non-JS objects
507   // because they may be represented as immediates without a
508   // map. Instead, we check against the map in the holder.
509   if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
510     object = holder;
511   }
512 
513   Code::Flags flags =
514       Code::ComputeMonomorphicFlags(Code::CALL_IC,
515                                     INTERCEPTOR,
516                                     NOT_IN_LOOP,
517                                     argc);
518   Object* code = map->FindInCodeCache(name, flags);
519   if (code->IsUndefined()) {
520     CallStubCompiler compiler(argc, NOT_IN_LOOP);
521     code = compiler.CompileCallInterceptor(object, holder, name);
522     if (code->IsFailure()) return code;
523     ASSERT_EQ(flags, Code::cast(code)->flags());
524     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
525     Object* result = map->UpdateCodeCache(name, Code::cast(code));
526     if (result->IsFailure()) return result;
527   }
528   return Set(name, map, Code::cast(code));
529 }
530 
531 
ComputeCallNormal(int argc,InLoopFlag in_loop,String * name,JSObject * receiver)532 Object* StubCache::ComputeCallNormal(int argc,
533                                      InLoopFlag in_loop,
534                                      String* name,
535                                      JSObject* receiver) {
536   Object* code = ComputeCallNormal(argc, in_loop);
537   if (code->IsFailure()) return code;
538   return Set(name, receiver->map(), Code::cast(code));
539 }
540 
541 
ComputeCallGlobal(int argc,InLoopFlag in_loop,String * name,JSObject * receiver,GlobalObject * holder,JSGlobalPropertyCell * cell,JSFunction * function)542 Object* StubCache::ComputeCallGlobal(int argc,
543                                      InLoopFlag in_loop,
544                                      String* name,
545                                      JSObject* receiver,
546                                      GlobalObject* holder,
547                                      JSGlobalPropertyCell* cell,
548                                      JSFunction* function) {
549   Code::Flags flags =
550       Code::ComputeMonomorphicFlags(Code::CALL_IC, NORMAL, in_loop, argc);
551   Object* code = receiver->map()->FindInCodeCache(name, flags);
552   if (code->IsUndefined()) {
553     // If the function hasn't been compiled yet, we cannot do it now
554     // because it may cause GC. To avoid this issue, we return an
555     // internal error which will make sure we do not update any
556     // caches.
557     if (!function->is_compiled()) return Failure::InternalError();
558     CallStubCompiler compiler(argc, in_loop);
559     code = compiler.CompileCallGlobal(receiver, holder, cell, function, name);
560     if (code->IsFailure()) return code;
561     ASSERT_EQ(flags, Code::cast(code)->flags());
562     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
563     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
564     if (result->IsFailure()) return code;
565   }
566   return Set(name, receiver->map(), Code::cast(code));
567 }
568 
569 
GetProbeValue(Code::Flags flags)570 static Object* GetProbeValue(Code::Flags flags) {
571   // Use raw_unchecked... so we don't get assert failures during GC.
572   NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache();
573   int entry = dictionary->FindEntry(flags);
574   if (entry != -1) return dictionary->ValueAt(entry);
575   return Heap::raw_unchecked_undefined_value();
576 }
577 
578 
ProbeCache(Code::Flags flags)579 static Object* ProbeCache(Code::Flags flags) {
580   Object* probe = GetProbeValue(flags);
581   if (probe != Heap::undefined_value()) return probe;
582   // Seed the cache with an undefined value to make sure that any
583   // generated code object can always be inserted into the cache
584   // without causing  allocation failures.
585   Object* result =
586       Heap::non_monomorphic_cache()->AtNumberPut(flags,
587                                                  Heap::undefined_value());
588   if (result->IsFailure()) return result;
589   Heap::public_set_non_monomorphic_cache(NumberDictionary::cast(result));
590   return probe;
591 }
592 
593 
FillCache(Object * code)594 static Object* FillCache(Object* code) {
595   if (code->IsCode()) {
596     int entry =
597         Heap::non_monomorphic_cache()->FindEntry(
598             Code::cast(code)->flags());
599     // The entry must be present see comment in ProbeCache.
600     ASSERT(entry != -1);
601     ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) ==
602            Heap::undefined_value());
603     Heap::non_monomorphic_cache()->ValueAtPut(entry, code);
604     CHECK(GetProbeValue(Code::cast(code)->flags()) == code);
605   }
606   return code;
607 }
608 
609 
FindCallInitialize(int argc,InLoopFlag in_loop)610 Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) {
611   Code::Flags flags =
612       Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc);
613   Object* result = ProbeCache(flags);
614   ASSERT(!result->IsUndefined());
615   // This might be called during the marking phase of the collector
616   // hence the unchecked cast.
617   return reinterpret_cast<Code*>(result);
618 }
619 
620 
ComputeCallInitialize(int argc,InLoopFlag in_loop)621 Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) {
622   Code::Flags flags =
623       Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc);
624   Object* probe = ProbeCache(flags);
625   if (!probe->IsUndefined()) return probe;
626   StubCompiler compiler;
627   return FillCache(compiler.CompileCallInitialize(flags));
628 }
629 
630 
ComputeCallPreMonomorphic(int argc,InLoopFlag in_loop)631 Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop) {
632   Code::Flags flags =
633       Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL, argc);
634   Object* probe = ProbeCache(flags);
635   if (!probe->IsUndefined()) return probe;
636   StubCompiler compiler;
637   return FillCache(compiler.CompileCallPreMonomorphic(flags));
638 }
639 
640 
ComputeCallNormal(int argc,InLoopFlag in_loop)641 Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) {
642   Code::Flags flags =
643       Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL, argc);
644   Object* probe = ProbeCache(flags);
645   if (!probe->IsUndefined()) return probe;
646   StubCompiler compiler;
647   return FillCache(compiler.CompileCallNormal(flags));
648 }
649 
650 
ComputeCallMegamorphic(int argc,InLoopFlag in_loop)651 Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) {
652   Code::Flags flags =
653       Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL, argc);
654   Object* probe = ProbeCache(flags);
655   if (!probe->IsUndefined()) return probe;
656   StubCompiler compiler;
657   return FillCache(compiler.CompileCallMegamorphic(flags));
658 }
659 
660 
ComputeCallMiss(int argc)661 Object* StubCache::ComputeCallMiss(int argc) {
662   Code::Flags flags =
663       Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL, argc);
664   Object* probe = ProbeCache(flags);
665   if (!probe->IsUndefined()) return probe;
666   StubCompiler compiler;
667   return FillCache(compiler.CompileCallMiss(flags));
668 }
669 
670 
671 #ifdef ENABLE_DEBUGGER_SUPPORT
ComputeCallDebugBreak(int argc)672 Object* StubCache::ComputeCallDebugBreak(int argc) {
673   Code::Flags flags =
674       Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc);
675   Object* probe = ProbeCache(flags);
676   if (!probe->IsUndefined()) return probe;
677   StubCompiler compiler;
678   return FillCache(compiler.CompileCallDebugBreak(flags));
679 }
680 
681 
ComputeCallDebugPrepareStepIn(int argc)682 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
683   Code::Flags flags =
684       Code::ComputeFlags(Code::CALL_IC,
685                          NOT_IN_LOOP,
686                          DEBUG_PREPARE_STEP_IN,
687                          NORMAL,
688                          argc);
689   Object* probe = ProbeCache(flags);
690   if (!probe->IsUndefined()) return probe;
691   StubCompiler compiler;
692   return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
693 }
694 #endif
695 
696 
ComputeLazyCompile(int argc)697 Object* StubCache::ComputeLazyCompile(int argc) {
698   Code::Flags flags =
699       Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, UNINITIALIZED, NORMAL, argc);
700   Object* probe = ProbeCache(flags);
701   if (!probe->IsUndefined()) return probe;
702   StubCompiler compiler;
703   Object* result = FillCache(compiler.CompileLazyCompile(flags));
704   if (result->IsCode()) {
705     Code* code = Code::cast(result);
706     USE(code);
707     LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
708                         code, code->arguments_count()));
709   }
710   return result;
711 }
712 
713 
Clear()714 void StubCache::Clear() {
715   for (int i = 0; i < kPrimaryTableSize; i++) {
716     primary_[i].key = Heap::empty_string();
717     primary_[i].value = Builtins::builtin(Builtins::Illegal);
718   }
719   for (int j = 0; j < kSecondaryTableSize; j++) {
720     secondary_[j].key = Heap::empty_string();
721     secondary_[j].value = Builtins::builtin(Builtins::Illegal);
722   }
723 }
724 
725 
726 // ------------------------------------------------------------------------
727 // StubCompiler implementation.
728 
729 
730 // Support function for computing call IC miss stubs.
ComputeCallMiss(int argc)731 Handle<Code> ComputeCallMiss(int argc) {
732   CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code);
733 }
734 
735 
736 
LoadCallbackProperty(Arguments args)737 Object* LoadCallbackProperty(Arguments args) {
738   Handle<JSObject> recv = args.at<JSObject>(0);
739   Handle<JSObject> holder = args.at<JSObject>(1);
740   AccessorInfo* callback = AccessorInfo::cast(args[2]);
741   Handle<Object> data = args.at<Object>(3);
742   Address getter_address = v8::ToCData<Address>(callback->getter());
743   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
744   ASSERT(fun != NULL);
745   Handle<String> name = args.at<String>(4);
746   // NOTE: If we can align the structure of an AccessorInfo with the
747   // locations of the arguments to this function maybe we don't have
748   // to explicitly create the structure but can just pass a pointer
749   // into the stack.
750   LOG(ApiNamedPropertyAccess("load", *recv, *name));
751   v8::AccessorInfo info(v8::Utils::ToLocal(recv),
752                         v8::Utils::ToLocal(data),
753                         v8::Utils::ToLocal(holder));
754   HandleScope scope;
755   v8::Handle<v8::Value> result;
756   {
757     // Leaving JavaScript.
758     VMState state(EXTERNAL);
759     result = fun(v8::Utils::ToLocal(name), info);
760   }
761   RETURN_IF_SCHEDULED_EXCEPTION();
762   if (result.IsEmpty()) return Heap::undefined_value();
763   return *v8::Utils::OpenHandle(*result);
764 }
765 
766 
StoreCallbackProperty(Arguments args)767 Object* StoreCallbackProperty(Arguments args) {
768   Handle<JSObject> recv = args.at<JSObject>(0);
769   AccessorInfo* callback = AccessorInfo::cast(args[1]);
770   Address setter_address = v8::ToCData<Address>(callback->setter());
771   v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
772   ASSERT(fun != NULL);
773   Handle<String> name = args.at<String>(2);
774   Handle<Object> value = args.at<Object>(3);
775   HandleScope scope;
776   Handle<Object> data(callback->data());
777   LOG(ApiNamedPropertyAccess("store", *recv, *name));
778   v8::AccessorInfo info(v8::Utils::ToLocal(recv),
779                         v8::Utils::ToLocal(data),
780                         v8::Utils::ToLocal(recv));
781   {
782     // Leaving JavaScript.
783     VMState state(EXTERNAL);
784     fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
785   }
786   RETURN_IF_SCHEDULED_EXCEPTION();
787   return *value;
788 }
789 
790 /**
791  * Attempts to load a property with an interceptor (which must be present),
792  * but doesn't search the prototype chain.
793  *
794  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
795  * provide any value for the given name.
796  */
LoadPropertyWithInterceptorOnly(Arguments args)797 Object* LoadPropertyWithInterceptorOnly(Arguments args) {
798   Handle<JSObject> receiver_handle = args.at<JSObject>(0);
799   Handle<JSObject> holder_handle = args.at<JSObject>(1);
800   Handle<String> name_handle = args.at<String>(2);
801   Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(3);
802   Handle<Object> data_handle = args.at<Object>(4);
803 
804   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
805   v8::NamedPropertyGetter getter =
806       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
807   ASSERT(getter != NULL);
808 
809   {
810     // Use the interceptor getter.
811     v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle),
812                           v8::Utils::ToLocal(data_handle),
813                           v8::Utils::ToLocal(holder_handle));
814     HandleScope scope;
815     v8::Handle<v8::Value> r;
816     {
817       // Leaving JavaScript.
818       VMState state(EXTERNAL);
819       r = getter(v8::Utils::ToLocal(name_handle), info);
820     }
821     RETURN_IF_SCHEDULED_EXCEPTION();
822     if (!r.IsEmpty()) {
823       return *v8::Utils::OpenHandle(*r);
824     }
825   }
826 
827   return Heap::no_interceptor_result_sentinel();
828 }
829 
830 
ThrowReferenceError(String * name)831 static Object* ThrowReferenceError(String* name) {
832   // If the load is non-contextual, just return the undefined result.
833   // Note that both keyed and non-keyed loads may end up here, so we
834   // can't use either LoadIC or KeyedLoadIC constructors.
835   IC ic(IC::NO_EXTRA_FRAME);
836   ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
837   if (!ic.is_contextual()) return Heap::undefined_value();
838 
839   // Throw a reference error.
840   HandleScope scope;
841   Handle<String> name_handle(name);
842   Handle<Object> error =
843       Factory::NewReferenceError("not_defined",
844                                   HandleVector(&name_handle, 1));
845   return Top::Throw(*error);
846 }
847 
848 
LoadWithInterceptor(Arguments * args,PropertyAttributes * attrs)849 static Object* LoadWithInterceptor(Arguments* args,
850                                    PropertyAttributes* attrs) {
851   Handle<JSObject> receiver_handle = args->at<JSObject>(0);
852   Handle<JSObject> holder_handle = args->at<JSObject>(1);
853   Handle<String> name_handle = args->at<String>(2);
854   Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(3);
855   Handle<Object> data_handle = args->at<Object>(4);
856 
857   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
858   v8::NamedPropertyGetter getter =
859       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
860   ASSERT(getter != NULL);
861 
862   {
863     // Use the interceptor getter.
864     v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle),
865                           v8::Utils::ToLocal(data_handle),
866                           v8::Utils::ToLocal(holder_handle));
867     HandleScope scope;
868     v8::Handle<v8::Value> r;
869     {
870       // Leaving JavaScript.
871       VMState state(EXTERNAL);
872       r = getter(v8::Utils::ToLocal(name_handle), info);
873     }
874     RETURN_IF_SCHEDULED_EXCEPTION();
875     if (!r.IsEmpty()) {
876       *attrs = NONE;
877       return *v8::Utils::OpenHandle(*r);
878     }
879   }
880 
881   Object* result = holder_handle->GetPropertyPostInterceptor(
882       *receiver_handle,
883       *name_handle,
884       attrs);
885   RETURN_IF_SCHEDULED_EXCEPTION();
886   return result;
887 }
888 
889 
890 /**
891  * Loads a property with an interceptor performing post interceptor
892  * lookup if interceptor failed.
893  */
LoadPropertyWithInterceptorForLoad(Arguments args)894 Object* LoadPropertyWithInterceptorForLoad(Arguments args) {
895   PropertyAttributes attr = NONE;
896   Object* result = LoadWithInterceptor(&args, &attr);
897   if (result->IsFailure()) return result;
898 
899   // If the property is present, return it.
900   if (attr != ABSENT) return result;
901   return ThrowReferenceError(String::cast(args[2]));
902 }
903 
904 
LoadPropertyWithInterceptorForCall(Arguments args)905 Object* LoadPropertyWithInterceptorForCall(Arguments args) {
906   PropertyAttributes attr;
907   Object* result = LoadWithInterceptor(&args, &attr);
908   RETURN_IF_SCHEDULED_EXCEPTION();
909   // This is call IC. In this case, we simply return the undefined result which
910   // will lead to an exception when trying to invoke the result as a
911   // function.
912   return result;
913 }
914 
915 
StoreInterceptorProperty(Arguments args)916 Object* StoreInterceptorProperty(Arguments args) {
917   JSObject* recv = JSObject::cast(args[0]);
918   String* name = String::cast(args[1]);
919   Object* value = args[2];
920   ASSERT(recv->HasNamedInterceptor());
921   PropertyAttributes attr = NONE;
922   Object* result = recv->SetPropertyWithInterceptor(name, value, attr);
923   return result;
924 }
925 
926 
CompileCallInitialize(Code::Flags flags)927 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) {
928   HandleScope scope;
929   int argc = Code::ExtractArgumentsCountFromFlags(flags);
930   CallIC::GenerateInitialize(masm(), argc);
931   Object* result = GetCodeWithFlags(flags, "CompileCallInitialize");
932   if (!result->IsFailure()) {
933     Counters::call_initialize_stubs.Increment();
934     Code* code = Code::cast(result);
935     USE(code);
936     LOG(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG,
937                         code, code->arguments_count()));
938   }
939   return result;
940 }
941 
942 
CompileCallPreMonomorphic(Code::Flags flags)943 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
944   HandleScope scope;
945   int argc = Code::ExtractArgumentsCountFromFlags(flags);
946   // The code of the PreMonomorphic stub is the same as the code
947   // of the Initialized stub.  They just differ on the code object flags.
948   CallIC::GenerateInitialize(masm(), argc);
949   Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
950   if (!result->IsFailure()) {
951     Counters::call_premonomorphic_stubs.Increment();
952     Code* code = Code::cast(result);
953     USE(code);
954     LOG(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG,
955                         code, code->arguments_count()));
956   }
957   return result;
958 }
959 
960 
CompileCallNormal(Code::Flags flags)961 Object* StubCompiler::CompileCallNormal(Code::Flags flags) {
962   HandleScope scope;
963   int argc = Code::ExtractArgumentsCountFromFlags(flags);
964   CallIC::GenerateNormal(masm(), argc);
965   Object* result = GetCodeWithFlags(flags, "CompileCallNormal");
966   if (!result->IsFailure()) {
967     Counters::call_normal_stubs.Increment();
968     Code* code = Code::cast(result);
969     USE(code);
970     LOG(CodeCreateEvent(Logger::CALL_NORMAL_TAG,
971                         code, code->arguments_count()));
972   }
973   return result;
974 }
975 
976 
CompileCallMegamorphic(Code::Flags flags)977 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
978   HandleScope scope;
979   int argc = Code::ExtractArgumentsCountFromFlags(flags);
980   CallIC::GenerateMegamorphic(masm(), argc);
981   Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic");
982   if (!result->IsFailure()) {
983     Counters::call_megamorphic_stubs.Increment();
984     Code* code = Code::cast(result);
985     USE(code);
986     LOG(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG,
987                         code, code->arguments_count()));
988   }
989   return result;
990 }
991 
992 
CompileCallMiss(Code::Flags flags)993 Object* StubCompiler::CompileCallMiss(Code::Flags flags) {
994   HandleScope scope;
995   int argc = Code::ExtractArgumentsCountFromFlags(flags);
996   CallIC::GenerateMiss(masm(), argc);
997   Object* result = GetCodeWithFlags(flags, "CompileCallMiss");
998   if (!result->IsFailure()) {
999     Counters::call_megamorphic_stubs.Increment();
1000     Code* code = Code::cast(result);
1001     USE(code);
1002     LOG(CodeCreateEvent(Logger::CALL_MISS_TAG, code, code->arguments_count()));
1003   }
1004   return result;
1005 }
1006 
1007 
1008 #ifdef ENABLE_DEBUGGER_SUPPORT
CompileCallDebugBreak(Code::Flags flags)1009 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
1010   HandleScope scope;
1011   Debug::GenerateCallICDebugBreak(masm());
1012   Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak");
1013   if (!result->IsFailure()) {
1014     Code* code = Code::cast(result);
1015     USE(code);
1016     LOG(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG,
1017                         code, code->arguments_count()));
1018   }
1019   return result;
1020 }
1021 
1022 
CompileCallDebugPrepareStepIn(Code::Flags flags)1023 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1024   HandleScope scope;
1025   // Use the same code for the the step in preparations as we do for
1026   // the miss case.
1027   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1028   CallIC::GenerateMiss(masm(), argc);
1029   Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1030   if (!result->IsFailure()) {
1031     Code* code = Code::cast(result);
1032     USE(code);
1033     LOG(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG,
1034                         code, code->arguments_count()));
1035   }
1036   return result;
1037 }
1038 #endif
1039 
1040 
GetCodeWithFlags(Code::Flags flags,const char * name)1041 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) {
1042   // Check for allocation failures during stub compilation.
1043   if (failure_->IsFailure()) return failure_;
1044 
1045   // Create code object in the heap.
1046   CodeDesc desc;
1047   masm_.GetCode(&desc);
1048   Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());
1049 #ifdef ENABLE_DISASSEMBLER
1050   if (FLAG_print_code_stubs && !result->IsFailure()) {
1051     Code::cast(result)->Disassemble(name);
1052   }
1053 #endif
1054   return result;
1055 }
1056 
1057 
GetCodeWithFlags(Code::Flags flags,String * name)1058 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
1059   if (FLAG_print_code_stubs && (name != NULL)) {
1060     return GetCodeWithFlags(flags, *name->ToCString());
1061   }
1062   return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1063 }
1064 
1065 
GetCode(PropertyType type,String * name)1066 Object* LoadStubCompiler::GetCode(PropertyType type, String* name) {
1067   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
1068   return GetCodeWithFlags(flags, name);
1069 }
1070 
1071 
GetCode(PropertyType type,String * name)1072 Object* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) {
1073   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type);
1074   return GetCodeWithFlags(flags, name);
1075 }
1076 
1077 
GetCode(PropertyType type,String * name)1078 Object* StoreStubCompiler::GetCode(PropertyType type, String* name) {
1079   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
1080   return GetCodeWithFlags(flags, name);
1081 }
1082 
1083 
GetCode(PropertyType type,String * name)1084 Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
1085   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
1086   return GetCodeWithFlags(flags, name);
1087 }
1088 
1089 
GetCode(PropertyType type,String * name)1090 Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
1091   int argc = arguments_.immediate();
1092   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
1093                                                     type,
1094                                                     in_loop_,
1095                                                     argc);
1096   return GetCodeWithFlags(flags, name);
1097 }
1098 
1099 
GetCode()1100 Object* ConstructStubCompiler::GetCode() {
1101   Code::Flags flags = Code::ComputeFlags(Code::STUB);
1102   Object* result = GetCodeWithFlags(flags, "ConstructStub");
1103   if (!result->IsFailure()) {
1104     Code* code = Code::cast(result);
1105     USE(code);
1106     LOG(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
1107   }
1108   return result;
1109 }
1110 
1111 
1112 } }  // namespace v8::internal
1113