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 result;
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(name, receiver, holder, callback);
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 result;
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 result;
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 result;
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 result;
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 result;
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(JSObject::cast(object),
488 holder,
489 index,
490 name);
491 if (code->IsFailure()) return code;
492 ASSERT_EQ(flags, Code::cast(code)->flags());
493 LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
494 Object* result = map->UpdateCodeCache(name, Code::cast(code));
495 if (result->IsFailure()) return result;
496 }
497 return Set(name, map, Code::cast(code));
498 }
499
500
ComputeCallInterceptor(int argc,String * name,Object * object,JSObject * holder)501 Object* StubCache::ComputeCallInterceptor(int argc,
502 String* name,
503 Object* object,
504 JSObject* holder) {
505 // Compute the check type and the map.
506 // If the object is a value, we use the prototype map for the cache.
507 Map* map = IC::GetCodeCacheMapForObject(object);
508
509 // TODO(1233596): We cannot do receiver map check for non-JS objects
510 // because they may be represented as immediates without a
511 // map. Instead, we check against the map in the holder.
512 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
513 object = holder;
514 }
515
516 Code::Flags flags =
517 Code::ComputeMonomorphicFlags(Code::CALL_IC,
518 INTERCEPTOR,
519 NOT_IN_LOOP,
520 argc);
521 Object* code = map->FindInCodeCache(name, flags);
522 if (code->IsUndefined()) {
523 CallStubCompiler compiler(argc, NOT_IN_LOOP);
524 code = compiler.CompileCallInterceptor(JSObject::cast(object),
525 holder,
526 name);
527 if (code->IsFailure()) return code;
528 ASSERT_EQ(flags, Code::cast(code)->flags());
529 LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
530 Object* result = map->UpdateCodeCache(name, Code::cast(code));
531 if (result->IsFailure()) return result;
532 }
533 return Set(name, map, Code::cast(code));
534 }
535
536
ComputeCallNormal(int argc,InLoopFlag in_loop,String * name,JSObject * receiver)537 Object* StubCache::ComputeCallNormal(int argc,
538 InLoopFlag in_loop,
539 String* name,
540 JSObject* receiver) {
541 Object* code = ComputeCallNormal(argc, in_loop);
542 if (code->IsFailure()) return code;
543 return Set(name, receiver->map(), Code::cast(code));
544 }
545
546
ComputeCallGlobal(int argc,InLoopFlag in_loop,String * name,JSObject * receiver,GlobalObject * holder,JSGlobalPropertyCell * cell,JSFunction * function)547 Object* StubCache::ComputeCallGlobal(int argc,
548 InLoopFlag in_loop,
549 String* name,
550 JSObject* receiver,
551 GlobalObject* holder,
552 JSGlobalPropertyCell* cell,
553 JSFunction* function) {
554 Code::Flags flags =
555 Code::ComputeMonomorphicFlags(Code::CALL_IC, NORMAL, in_loop, argc);
556 Object* code = receiver->map()->FindInCodeCache(name, flags);
557 if (code->IsUndefined()) {
558 // If the function hasn't been compiled yet, we cannot do it now
559 // because it may cause GC. To avoid this issue, we return an
560 // internal error which will make sure we do not update any
561 // caches.
562 if (!function->is_compiled()) return Failure::InternalError();
563 CallStubCompiler compiler(argc, in_loop);
564 code = compiler.CompileCallGlobal(receiver, holder, cell, function, name);
565 if (code->IsFailure()) return code;
566 ASSERT_EQ(flags, Code::cast(code)->flags());
567 LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
568 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
569 if (result->IsFailure()) return result;
570 }
571 return Set(name, receiver->map(), Code::cast(code));
572 }
573
574
GetProbeValue(Code::Flags flags)575 static Object* GetProbeValue(Code::Flags flags) {
576 // Use raw_unchecked... so we don't get assert failures during GC.
577 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache();
578 int entry = dictionary->FindEntry(flags);
579 if (entry != -1) return dictionary->ValueAt(entry);
580 return Heap::raw_unchecked_undefined_value();
581 }
582
583
ProbeCache(Code::Flags flags)584 static Object* ProbeCache(Code::Flags flags) {
585 Object* probe = GetProbeValue(flags);
586 if (probe != Heap::undefined_value()) return probe;
587 // Seed the cache with an undefined value to make sure that any
588 // generated code object can always be inserted into the cache
589 // without causing allocation failures.
590 Object* result =
591 Heap::non_monomorphic_cache()->AtNumberPut(flags,
592 Heap::undefined_value());
593 if (result->IsFailure()) return result;
594 Heap::public_set_non_monomorphic_cache(NumberDictionary::cast(result));
595 return probe;
596 }
597
598
FillCache(Object * code)599 static Object* FillCache(Object* code) {
600 if (code->IsCode()) {
601 int entry =
602 Heap::non_monomorphic_cache()->FindEntry(
603 Code::cast(code)->flags());
604 // The entry must be present see comment in ProbeCache.
605 ASSERT(entry != -1);
606 ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) ==
607 Heap::undefined_value());
608 Heap::non_monomorphic_cache()->ValueAtPut(entry, code);
609 CHECK(GetProbeValue(Code::cast(code)->flags()) == code);
610 }
611 return code;
612 }
613
614
FindCallInitialize(int argc,InLoopFlag in_loop)615 Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) {
616 Code::Flags flags =
617 Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc);
618 Object* result = ProbeCache(flags);
619 ASSERT(!result->IsUndefined());
620 // This might be called during the marking phase of the collector
621 // hence the unchecked cast.
622 return reinterpret_cast<Code*>(result);
623 }
624
625
ComputeCallInitialize(int argc,InLoopFlag in_loop)626 Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) {
627 Code::Flags flags =
628 Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc);
629 Object* probe = ProbeCache(flags);
630 if (!probe->IsUndefined()) return probe;
631 StubCompiler compiler;
632 return FillCache(compiler.CompileCallInitialize(flags));
633 }
634
635
ComputeCallPreMonomorphic(int argc,InLoopFlag in_loop)636 Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop) {
637 Code::Flags flags =
638 Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL, argc);
639 Object* probe = ProbeCache(flags);
640 if (!probe->IsUndefined()) return probe;
641 StubCompiler compiler;
642 return FillCache(compiler.CompileCallPreMonomorphic(flags));
643 }
644
645
ComputeCallNormal(int argc,InLoopFlag in_loop)646 Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) {
647 Code::Flags flags =
648 Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL, argc);
649 Object* probe = ProbeCache(flags);
650 if (!probe->IsUndefined()) return probe;
651 StubCompiler compiler;
652 return FillCache(compiler.CompileCallNormal(flags));
653 }
654
655
ComputeCallMegamorphic(int argc,InLoopFlag in_loop)656 Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) {
657 Code::Flags flags =
658 Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL, argc);
659 Object* probe = ProbeCache(flags);
660 if (!probe->IsUndefined()) return probe;
661 StubCompiler compiler;
662 return FillCache(compiler.CompileCallMegamorphic(flags));
663 }
664
665
ComputeCallMiss(int argc)666 Object* StubCache::ComputeCallMiss(int argc) {
667 Code::Flags flags =
668 Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL, argc);
669 Object* probe = ProbeCache(flags);
670 if (!probe->IsUndefined()) return probe;
671 StubCompiler compiler;
672 return FillCache(compiler.CompileCallMiss(flags));
673 }
674
675
676 #ifdef ENABLE_DEBUGGER_SUPPORT
ComputeCallDebugBreak(int argc)677 Object* StubCache::ComputeCallDebugBreak(int argc) {
678 Code::Flags flags =
679 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc);
680 Object* probe = ProbeCache(flags);
681 if (!probe->IsUndefined()) return probe;
682 StubCompiler compiler;
683 return FillCache(compiler.CompileCallDebugBreak(flags));
684 }
685
686
ComputeCallDebugPrepareStepIn(int argc)687 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
688 Code::Flags flags =
689 Code::ComputeFlags(Code::CALL_IC,
690 NOT_IN_LOOP,
691 DEBUG_PREPARE_STEP_IN,
692 NORMAL,
693 argc);
694 Object* probe = ProbeCache(flags);
695 if (!probe->IsUndefined()) return probe;
696 StubCompiler compiler;
697 return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
698 }
699 #endif
700
701
ComputeLazyCompile(int argc)702 Object* StubCache::ComputeLazyCompile(int argc) {
703 Code::Flags flags =
704 Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, UNINITIALIZED, NORMAL, argc);
705 Object* probe = ProbeCache(flags);
706 if (!probe->IsUndefined()) return probe;
707 StubCompiler compiler;
708 Object* result = FillCache(compiler.CompileLazyCompile(flags));
709 if (result->IsCode()) {
710 Code* code = Code::cast(result);
711 USE(code);
712 LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
713 code, code->arguments_count()));
714 }
715 return result;
716 }
717
718
Clear()719 void StubCache::Clear() {
720 for (int i = 0; i < kPrimaryTableSize; i++) {
721 primary_[i].key = Heap::empty_string();
722 primary_[i].value = Builtins::builtin(Builtins::Illegal);
723 }
724 for (int j = 0; j < kSecondaryTableSize; j++) {
725 secondary_[j].key = Heap::empty_string();
726 secondary_[j].value = Builtins::builtin(Builtins::Illegal);
727 }
728 }
729
730
731 // ------------------------------------------------------------------------
732 // StubCompiler implementation.
733
734
735 // Support function for computing call IC miss stubs.
ComputeCallMiss(int argc)736 Handle<Code> ComputeCallMiss(int argc) {
737 CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code);
738 }
739
740
741
LoadCallbackProperty(Arguments args)742 Object* LoadCallbackProperty(Arguments args) {
743 ASSERT(args[0]->IsJSObject());
744 ASSERT(args[1]->IsJSObject());
745 AccessorInfo* callback = AccessorInfo::cast(args[2]);
746 Address getter_address = v8::ToCData<Address>(callback->getter());
747 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
748 ASSERT(fun != NULL);
749 CustomArguments custom_args(callback->data(),
750 JSObject::cast(args[0]),
751 JSObject::cast(args[1]));
752 v8::AccessorInfo info(custom_args.end());
753 HandleScope scope;
754 v8::Handle<v8::Value> result;
755 {
756 // Leaving JavaScript.
757 VMState state(EXTERNAL);
758 #ifdef ENABLE_LOGGING_AND_PROFILING
759 state.set_external_callback(getter_address);
760 #endif
761 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
762 }
763 RETURN_IF_SCHEDULED_EXCEPTION();
764 if (result.IsEmpty()) return Heap::undefined_value();
765 return *v8::Utils::OpenHandle(*result);
766 }
767
768
StoreCallbackProperty(Arguments args)769 Object* StoreCallbackProperty(Arguments args) {
770 JSObject* recv = JSObject::cast(args[0]);
771 AccessorInfo* callback = AccessorInfo::cast(args[1]);
772 Address setter_address = v8::ToCData<Address>(callback->setter());
773 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
774 ASSERT(fun != NULL);
775 Handle<String> name = args.at<String>(2);
776 Handle<Object> value = args.at<Object>(3);
777 HandleScope scope;
778 LOG(ApiNamedPropertyAccess("store", recv, *name));
779 CustomArguments custom_args(callback->data(), recv, recv);
780 v8::AccessorInfo info(custom_args.end());
781 {
782 // Leaving JavaScript.
783 VMState state(EXTERNAL);
784 #ifdef ENABLE_LOGGING_AND_PROFILING
785 state.set_external_callback(setter_address);
786 #endif
787 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
788 }
789 RETURN_IF_SCHEDULED_EXCEPTION();
790 return *value;
791 }
792
793 /**
794 * Attempts to load a property with an interceptor (which must be present),
795 * but doesn't search the prototype chain.
796 *
797 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
798 * provide any value for the given name.
799 */
LoadPropertyWithInterceptorOnly(Arguments args)800 Object* LoadPropertyWithInterceptorOnly(Arguments args) {
801 JSObject* receiver_handle = JSObject::cast(args[0]);
802 JSObject* holder_handle = JSObject::cast(args[1]);
803 Handle<String> name_handle = args.at<String>(2);
804 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(3);
805 Object* data_handle = args[4];
806
807 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
808 v8::NamedPropertyGetter getter =
809 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
810 ASSERT(getter != NULL);
811
812 {
813 // Use the interceptor getter.
814 CustomArguments args(data_handle, receiver_handle, holder_handle);
815 v8::AccessorInfo info(args.end());
816 HandleScope scope;
817 v8::Handle<v8::Value> r;
818 {
819 // Leaving JavaScript.
820 VMState state(EXTERNAL);
821 r = getter(v8::Utils::ToLocal(name_handle), info);
822 }
823 RETURN_IF_SCHEDULED_EXCEPTION();
824 if (!r.IsEmpty()) {
825 return *v8::Utils::OpenHandle(*r);
826 }
827 }
828
829 return Heap::no_interceptor_result_sentinel();
830 }
831
832
ThrowReferenceError(String * name)833 static Object* ThrowReferenceError(String* name) {
834 // If the load is non-contextual, just return the undefined result.
835 // Note that both keyed and non-keyed loads may end up here, so we
836 // can't use either LoadIC or KeyedLoadIC constructors.
837 IC ic(IC::NO_EXTRA_FRAME);
838 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
839 if (!ic.SlowIsContextual()) return Heap::undefined_value();
840
841 // Throw a reference error.
842 HandleScope scope;
843 Handle<String> name_handle(name);
844 Handle<Object> error =
845 Factory::NewReferenceError("not_defined",
846 HandleVector(&name_handle, 1));
847 return Top::Throw(*error);
848 }
849
850
LoadWithInterceptor(Arguments * args,PropertyAttributes * attrs)851 static Object* LoadWithInterceptor(Arguments* args,
852 PropertyAttributes* attrs) {
853 Handle<JSObject> receiver_handle = args->at<JSObject>(0);
854 Handle<JSObject> holder_handle = args->at<JSObject>(1);
855 Handle<String> name_handle = args->at<String>(2);
856 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(3);
857 Handle<Object> data_handle = args->at<Object>(4);
858
859 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
860 v8::NamedPropertyGetter getter =
861 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
862 ASSERT(getter != NULL);
863
864 {
865 // Use the interceptor getter.
866 CustomArguments args(*data_handle, *receiver_handle, *holder_handle);
867 v8::AccessorInfo info(args.end());
868 HandleScope scope;
869 v8::Handle<v8::Value> r;
870 {
871 // Leaving JavaScript.
872 VMState state(EXTERNAL);
873 r = getter(v8::Utils::ToLocal(name_handle), info);
874 }
875 RETURN_IF_SCHEDULED_EXCEPTION();
876 if (!r.IsEmpty()) {
877 *attrs = NONE;
878 return *v8::Utils::OpenHandle(*r);
879 }
880 }
881
882 Object* result = holder_handle->GetPropertyPostInterceptor(
883 *receiver_handle,
884 *name_handle,
885 attrs);
886 RETURN_IF_SCHEDULED_EXCEPTION();
887 return result;
888 }
889
890
891 /**
892 * Loads a property with an interceptor performing post interceptor
893 * lookup if interceptor failed.
894 */
LoadPropertyWithInterceptorForLoad(Arguments args)895 Object* LoadPropertyWithInterceptorForLoad(Arguments args) {
896 PropertyAttributes attr = NONE;
897 Object* result = LoadWithInterceptor(&args, &attr);
898 if (result->IsFailure()) return result;
899
900 // If the property is present, return it.
901 if (attr != ABSENT) return result;
902 return ThrowReferenceError(String::cast(args[2]));
903 }
904
905
LoadPropertyWithInterceptorForCall(Arguments args)906 Object* LoadPropertyWithInterceptorForCall(Arguments args) {
907 PropertyAttributes attr;
908 Object* result = LoadWithInterceptor(&args, &attr);
909 RETURN_IF_SCHEDULED_EXCEPTION();
910 // This is call IC. In this case, we simply return the undefined result which
911 // will lead to an exception when trying to invoke the result as a
912 // function.
913 return result;
914 }
915
916
StoreInterceptorProperty(Arguments args)917 Object* StoreInterceptorProperty(Arguments args) {
918 JSObject* recv = JSObject::cast(args[0]);
919 String* name = String::cast(args[1]);
920 Object* value = args[2];
921 ASSERT(recv->HasNamedInterceptor());
922 PropertyAttributes attr = NONE;
923 Object* result = recv->SetPropertyWithInterceptor(name, value, attr);
924 return result;
925 }
926
927
KeyedLoadPropertyWithInterceptor(Arguments args)928 Object* KeyedLoadPropertyWithInterceptor(Arguments args) {
929 JSObject* receiver = JSObject::cast(args[0]);
930 uint32_t index = Smi::cast(args[1])->value();
931 return receiver->GetElementWithInterceptor(receiver, index);
932 }
933
934
CompileCallInitialize(Code::Flags flags)935 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) {
936 HandleScope scope;
937 int argc = Code::ExtractArgumentsCountFromFlags(flags);
938 CallIC::GenerateInitialize(masm(), argc);
939 Object* result = GetCodeWithFlags(flags, "CompileCallInitialize");
940 if (!result->IsFailure()) {
941 Counters::call_initialize_stubs.Increment();
942 Code* code = Code::cast(result);
943 USE(code);
944 LOG(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG,
945 code, code->arguments_count()));
946 }
947 return result;
948 }
949
950
CompileCallPreMonomorphic(Code::Flags flags)951 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
952 HandleScope scope;
953 int argc = Code::ExtractArgumentsCountFromFlags(flags);
954 // The code of the PreMonomorphic stub is the same as the code
955 // of the Initialized stub. They just differ on the code object flags.
956 CallIC::GenerateInitialize(masm(), argc);
957 Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
958 if (!result->IsFailure()) {
959 Counters::call_premonomorphic_stubs.Increment();
960 Code* code = Code::cast(result);
961 USE(code);
962 LOG(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG,
963 code, code->arguments_count()));
964 }
965 return result;
966 }
967
968
CompileCallNormal(Code::Flags flags)969 Object* StubCompiler::CompileCallNormal(Code::Flags flags) {
970 HandleScope scope;
971 int argc = Code::ExtractArgumentsCountFromFlags(flags);
972 CallIC::GenerateNormal(masm(), argc);
973 Object* result = GetCodeWithFlags(flags, "CompileCallNormal");
974 if (!result->IsFailure()) {
975 Counters::call_normal_stubs.Increment();
976 Code* code = Code::cast(result);
977 USE(code);
978 LOG(CodeCreateEvent(Logger::CALL_NORMAL_TAG,
979 code, code->arguments_count()));
980 }
981 return result;
982 }
983
984
CompileCallMegamorphic(Code::Flags flags)985 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
986 HandleScope scope;
987 int argc = Code::ExtractArgumentsCountFromFlags(flags);
988 CallIC::GenerateMegamorphic(masm(), argc);
989 Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic");
990 if (!result->IsFailure()) {
991 Counters::call_megamorphic_stubs.Increment();
992 Code* code = Code::cast(result);
993 USE(code);
994 LOG(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG,
995 code, code->arguments_count()));
996 }
997 return result;
998 }
999
1000
CompileCallMiss(Code::Flags flags)1001 Object* StubCompiler::CompileCallMiss(Code::Flags flags) {
1002 HandleScope scope;
1003 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1004 CallIC::GenerateMiss(masm(), argc);
1005 Object* result = GetCodeWithFlags(flags, "CompileCallMiss");
1006 if (!result->IsFailure()) {
1007 Counters::call_megamorphic_stubs.Increment();
1008 Code* code = Code::cast(result);
1009 USE(code);
1010 LOG(CodeCreateEvent(Logger::CALL_MISS_TAG, code, code->arguments_count()));
1011 }
1012 return result;
1013 }
1014
1015
1016 #ifdef ENABLE_DEBUGGER_SUPPORT
CompileCallDebugBreak(Code::Flags flags)1017 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
1018 HandleScope scope;
1019 Debug::GenerateCallICDebugBreak(masm());
1020 Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak");
1021 if (!result->IsFailure()) {
1022 Code* code = Code::cast(result);
1023 USE(code);
1024 LOG(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG,
1025 code, code->arguments_count()));
1026 }
1027 return result;
1028 }
1029
1030
CompileCallDebugPrepareStepIn(Code::Flags flags)1031 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1032 HandleScope scope;
1033 // Use the same code for the the step in preparations as we do for
1034 // the miss case.
1035 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1036 CallIC::GenerateMiss(masm(), argc);
1037 Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1038 if (!result->IsFailure()) {
1039 Code* code = Code::cast(result);
1040 USE(code);
1041 LOG(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG,
1042 code, code->arguments_count()));
1043 }
1044 return result;
1045 }
1046 #endif
1047
1048
GetCodeWithFlags(Code::Flags flags,const char * name)1049 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) {
1050 // Check for allocation failures during stub compilation.
1051 if (failure_->IsFailure()) return failure_;
1052
1053 // Create code object in the heap.
1054 CodeDesc desc;
1055 masm_.GetCode(&desc);
1056 Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());
1057 #ifdef ENABLE_DISASSEMBLER
1058 if (FLAG_print_code_stubs && !result->IsFailure()) {
1059 Code::cast(result)->Disassemble(name);
1060 }
1061 #endif
1062 return result;
1063 }
1064
1065
GetCodeWithFlags(Code::Flags flags,String * name)1066 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
1067 if (FLAG_print_code_stubs && (name != NULL)) {
1068 return GetCodeWithFlags(flags, *name->ToCString());
1069 }
1070 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1071 }
1072
1073
LookupPostInterceptor(JSObject * holder,String * name,LookupResult * lookup)1074 void StubCompiler::LookupPostInterceptor(JSObject* holder,
1075 String* name,
1076 LookupResult* lookup) {
1077 holder->LocalLookupRealNamedProperty(name, lookup);
1078 if (!lookup->IsProperty()) {
1079 lookup->NotFound();
1080 Object* proto = holder->GetPrototype();
1081 if (proto != Heap::null_value()) {
1082 proto->Lookup(name, lookup);
1083 }
1084 }
1085 }
1086
1087
1088
GetCode(PropertyType type,String * name)1089 Object* LoadStubCompiler::GetCode(PropertyType type, String* name) {
1090 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
1091 return GetCodeWithFlags(flags, name);
1092 }
1093
1094
GetCode(PropertyType type,String * name)1095 Object* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) {
1096 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type);
1097 return GetCodeWithFlags(flags, name);
1098 }
1099
1100
GetCode(PropertyType type,String * name)1101 Object* StoreStubCompiler::GetCode(PropertyType type, String* name) {
1102 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
1103 return GetCodeWithFlags(flags, name);
1104 }
1105
1106
GetCode(PropertyType type,String * name)1107 Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
1108 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
1109 return GetCodeWithFlags(flags, name);
1110 }
1111
1112
GetCode(PropertyType type,String * name)1113 Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
1114 int argc = arguments_.immediate();
1115 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
1116 type,
1117 in_loop_,
1118 argc);
1119 return GetCodeWithFlags(flags, name);
1120 }
1121
1122
GetCode()1123 Object* ConstructStubCompiler::GetCode() {
1124 Code::Flags flags = Code::ComputeFlags(Code::STUB);
1125 Object* result = GetCodeWithFlags(flags, "ConstructStub");
1126 if (!result->IsFailure()) {
1127 Code* code = Code::cast(result);
1128 USE(code);
1129 LOG(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
1130 }
1131 return result;
1132 }
1133
1134
1135 } } // namespace v8::internal
1136