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