v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
stub-cache.cc
Go to the documentation of this file.
1 // Copyright 2012 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 "ast.h"
33 #include "code-stubs.h"
34 #include "gdb-jit.h"
35 #include "ic-inl.h"
36 #include "stub-cache.h"
37 #include "vm-state-inl.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 // -----------------------------------------------------------------------
43 // StubCache implementation.
44 
45 
46 StubCache::StubCache(Isolate* isolate, Zone* zone)
47  : isolate_(isolate) {
48  ASSERT(isolate == Isolate::Current());
49 }
50 
51 
52 void StubCache::Initialize() {
53  ASSERT(IsPowerOf2(kPrimaryTableSize));
54  ASSERT(IsPowerOf2(kSecondaryTableSize));
55  Clear();
56 }
57 
58 
59 Code* StubCache::Set(String* name, Map* map, Code* code) {
60  // Get the flags from the code.
61  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
62 
63  // Validate that the name does not move on scavenge, and that we
64  // can use identity checks instead of string equality checks.
65  ASSERT(!heap()->InNewSpace(name));
66  ASSERT(name->IsSymbol());
67 
68  // The state bits are not important to the hash function because
69  // the stub cache only contains monomorphic stubs. Make sure that
70  // the bits are the least significant so they will be the ones
71  // masked out.
72  ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
73  STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
74 
75  // Make sure that the code type is not included in the hash.
76  ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
77 
78  // Compute the primary entry.
79  int primary_offset = PrimaryOffset(name, flags, map);
80  Entry* primary = entry(primary_, primary_offset);
81  Code* old_code = primary->value;
82 
83  // If the primary entry has useful data in it, we retire it to the
84  // secondary cache before overwriting it.
85  if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
86  Map* old_map = primary->map;
87  Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
88  int seed = PrimaryOffset(primary->key, old_flags, old_map);
89  int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
90  Entry* secondary = entry(secondary_, secondary_offset);
91  *secondary = *primary;
92  }
93 
94  // Update primary cache.
95  primary->key = name;
96  primary->value = code;
97  primary->map = map;
98  isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
99  return code;
100 }
101 
102 
103 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
104  Handle<JSObject> receiver) {
105  ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
106  // If no global objects are present in the prototype chain, the load
107  // nonexistent IC stub can be shared for all names for a given map
108  // and we use the empty string for the map cache in that case. If
109  // there are global objects involved, we need to check global
110  // property cells in the stub and therefore the stub will be
111  // specific to the name.
112  Handle<String> cache_name = factory()->empty_string();
113  if (receiver->IsGlobalObject()) cache_name = name;
114  Handle<JSObject> last = receiver;
115  while (last->GetPrototype() != heap()->null_value()) {
116  last = Handle<JSObject>(JSObject::cast(last->GetPrototype()));
117  if (last->IsGlobalObject()) cache_name = name;
118  }
119  // Compile the stub that is either shared for all names or
120  // name specific if there are global objects involved.
122  Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::NONEXISTENT);
123  Handle<Object> probe(receiver->map()->FindInCodeCache(*cache_name, flags));
124  if (probe->IsCode()) return Handle<Code>::cast(probe);
125 
126  LoadStubCompiler compiler(isolate_);
128  compiler.CompileLoadNonexistent(cache_name, receiver, last);
129  PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name));
130  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code));
131  JSObject::UpdateMapCodeCache(receiver, cache_name, code);
132  return code;
133 }
134 
135 
136 Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
137  Handle<JSObject> receiver,
138  Handle<JSObject> holder,
139  int field_index) {
140  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
141  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::FIELD);
142  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
143  if (probe->IsCode()) return Handle<Code>::cast(probe);
144 
145  LoadStubCompiler compiler(isolate_);
147  compiler.CompileLoadField(receiver, holder, field_index, name);
148  PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
149  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
150  JSObject::UpdateMapCodeCache(receiver, name, code);
151  return code;
152 }
153 
154 
155 Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
156  Handle<JSObject> receiver,
157  Handle<JSObject> holder,
158  Handle<AccessorInfo> callback) {
159  ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
160  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
162  Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::CALLBACKS);
163  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
164  if (probe->IsCode()) return Handle<Code>::cast(probe);
165 
166  LoadStubCompiler compiler(isolate_);
168  compiler.CompileLoadCallback(name, receiver, holder, callback);
169  PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
170  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
171  JSObject::UpdateMapCodeCache(receiver, name, code);
172  return code;
173 }
174 
175 
176 Handle<Code> StubCache::ComputeLoadViaGetter(Handle<String> name,
177  Handle<JSObject> receiver,
178  Handle<JSObject> holder,
179  Handle<JSFunction> getter) {
180  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
182  Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::CALLBACKS);
183  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
184  if (probe->IsCode()) return Handle<Code>::cast(probe);
185 
186  LoadStubCompiler compiler(isolate_);
188  compiler.CompileLoadViaGetter(name, receiver, holder, getter);
189  PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
190  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
191  JSObject::UpdateMapCodeCache(receiver, name, code);
192  return code;
193 }
194 
195 
196 Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
197  Handle<JSObject> receiver,
198  Handle<JSObject> holder,
199  Handle<JSFunction> value) {
200  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
202  Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::CONSTANT_FUNCTION);
203  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
204  if (probe->IsCode()) return Handle<Code>::cast(probe);
205 
206  LoadStubCompiler compiler(isolate_);
208  compiler.CompileLoadConstant(receiver, holder, value, name);
209  PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
210  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
211  JSObject::UpdateMapCodeCache(receiver, name, code);
212  return code;
213 }
214 
215 
216 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
217  Handle<JSObject> receiver,
218  Handle<JSObject> holder) {
219  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
221  Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::INTERCEPTOR);
222  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
223  if (probe->IsCode()) return Handle<Code>::cast(probe);
224 
225  LoadStubCompiler compiler(isolate_);
227  compiler.CompileLoadInterceptor(receiver, holder, name);
228  PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
229  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
230  JSObject::UpdateMapCodeCache(receiver, name, code);
231  return code;
232 }
233 
234 
235 Handle<Code> StubCache::ComputeLoadNormal() {
236  return isolate_->builtins()->LoadIC_Normal();
237 }
238 
239 
240 Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
241  Handle<JSObject> receiver,
242  Handle<GlobalObject> holder,
244  bool is_dont_delete) {
245  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
247  Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::NORMAL);
248  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
249  if (probe->IsCode()) return Handle<Code>::cast(probe);
250 
251  LoadStubCompiler compiler(isolate_);
253  compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
254  PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
255  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
256  JSObject::UpdateMapCodeCache(receiver, name, code);
257  return code;
258 }
259 
260 
261 Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
262  Handle<JSObject> receiver,
263  Handle<JSObject> holder,
264  int field_index) {
265  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
267  Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::FIELD);
268  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
269  if (probe->IsCode()) return Handle<Code>::cast(probe);
270 
271  KeyedLoadStubCompiler compiler(isolate_);
273  compiler.CompileLoadField(name, receiver, holder, field_index);
274  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
275  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
276  JSObject::UpdateMapCodeCache(receiver, name, code);
277  return code;
278 }
279 
280 
281 Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
282  Handle<JSObject> receiver,
283  Handle<JSObject> holder,
284  Handle<JSFunction> value) {
285  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
286  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC,
288  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
289  if (probe->IsCode()) return Handle<Code>::cast(probe);
290 
291  KeyedLoadStubCompiler compiler(isolate_);
293  compiler.CompileLoadConstant(name, receiver, holder, value);
294  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
295  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
296  JSObject::UpdateMapCodeCache(receiver, name, code);
297  return code;
298 }
299 
300 
301 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
302  Handle<JSObject> receiver,
303  Handle<JSObject> holder) {
304  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
306  Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
307  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
308  if (probe->IsCode()) return Handle<Code>::cast(probe);
309 
310  KeyedLoadStubCompiler compiler(isolate_);
311  Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name);
312  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
313  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
314  JSObject::UpdateMapCodeCache(receiver, name, code);
315  return code;
316 }
317 
318 
319 Handle<Code> StubCache::ComputeKeyedLoadCallback(
320  Handle<String> name,
321  Handle<JSObject> receiver,
322  Handle<JSObject> holder,
323  Handle<AccessorInfo> callback) {
324  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
326  Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
327  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
328  if (probe->IsCode()) return Handle<Code>::cast(probe);
329 
330  KeyedLoadStubCompiler compiler(isolate_);
332  compiler.CompileLoadCallback(name, receiver, holder, callback);
333  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
334  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
335  JSObject::UpdateMapCodeCache(receiver, name, code);
336  return code;
337 }
338 
339 
340 Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
341  Handle<JSArray> receiver) {
343  Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
344  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
345  if (probe->IsCode()) return Handle<Code>::cast(probe);
346 
347  KeyedLoadStubCompiler compiler(isolate_);
348  Handle<Code> code = compiler.CompileLoadArrayLength(name);
349  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
350  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
351  JSObject::UpdateMapCodeCache(receiver, name, code);
352  return code;
353 }
354 
355 
356 Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name,
357  Handle<String> receiver) {
359  Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
360  Handle<Map> map(receiver->map());
361  Handle<Object> probe(map->FindInCodeCache(*name, flags));
362  if (probe->IsCode()) return Handle<Code>::cast(probe);
363 
364  KeyedLoadStubCompiler compiler(isolate_);
365  Handle<Code> code = compiler.CompileLoadStringLength(name);
366  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
367  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
368  Map::UpdateCodeCache(map, name, code);
369  return code;
370 }
371 
372 
373 Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
374  Handle<String> name,
375  Handle<JSFunction> receiver) {
377  Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
378  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
379  if (probe->IsCode()) return Handle<Code>::cast(probe);
380 
381  KeyedLoadStubCompiler compiler(isolate_);
383  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
384  GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
385  JSObject::UpdateMapCodeCache(receiver, name, code);
386  return code;
387 }
388 
389 
390 Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
391  Handle<JSObject> receiver,
392  int field_index,
393  Handle<Map> transition,
394  StrictModeFlag strict_mode) {
395  Code::StubType type =
396  (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
397  Code::Flags flags = Code::ComputeMonomorphicFlags(
398  Code::STORE_IC, type, strict_mode);
399  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
400  if (probe->IsCode()) return Handle<Code>::cast(probe);
401 
402  StoreStubCompiler compiler(isolate_, strict_mode);
404  compiler.CompileStoreField(receiver, field_index, transition, name);
405  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
406  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
407  JSObject::UpdateMapCodeCache(receiver, name, code);
408  return code;
409 }
410 
411 
412 Handle<Code> StubCache::ComputeKeyedLoadOrStoreElement(
413  Handle<Map> receiver_map,
414  KeyedIC::StubKind stub_kind,
415  StrictModeFlag strict_mode) {
416  KeyedAccessGrowMode grow_mode =
417  KeyedIC::GetGrowModeFromStubKind(stub_kind);
418  Code::ExtraICState extra_state =
419  Code::ComputeExtraICState(grow_mode, strict_mode);
421  Code::ComputeMonomorphicFlags(
422  stub_kind == KeyedIC::LOAD ? Code::KEYED_LOAD_IC
423  : Code::KEYED_STORE_IC,
424  Code::NORMAL,
425  extra_state);
426  Handle<String> name;
427  switch (stub_kind) {
428  case KeyedIC::LOAD:
429  name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol();
430  break;
431  case KeyedIC::STORE_NO_TRANSITION:
432  name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol();
433  break;
434  case KeyedIC::STORE_AND_GROW_NO_TRANSITION:
435  name = isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_symbol();
436  break;
437  default:
438  UNREACHABLE();
439  break;
440  }
441  Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags));
442  if (probe->IsCode()) return Handle<Code>::cast(probe);
443 
445  switch (stub_kind) {
446  case KeyedIC::LOAD: {
447  KeyedLoadStubCompiler compiler(isolate_);
448  code = compiler.CompileLoadElement(receiver_map);
449  break;
450  }
451  case KeyedIC::STORE_AND_GROW_NO_TRANSITION: {
452  KeyedStoreStubCompiler compiler(isolate_, strict_mode,
454  code = compiler.CompileStoreElement(receiver_map);
455  break;
456  }
457  case KeyedIC::STORE_NO_TRANSITION: {
458  KeyedStoreStubCompiler compiler(isolate_, strict_mode,
460  code = compiler.CompileStoreElement(receiver_map);
461  break;
462  }
463  default:
464  UNREACHABLE();
465  break;
466  }
467 
468  ASSERT(!code.is_null());
469 
470  if (stub_kind == KeyedIC::LOAD) {
471  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0));
472  } else {
473  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0));
474  }
475  Map::UpdateCodeCache(receiver_map, name, code);
476  return code;
477 }
478 
479 
480 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
481  return (strict_mode == kStrictMode)
482  ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
483  : isolate_->builtins()->Builtins::StoreIC_Normal();
484 }
485 
486 
487 Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name,
488  Handle<GlobalObject> receiver,
490  StrictModeFlag strict_mode) {
491  Code::Flags flags = Code::ComputeMonomorphicFlags(
492  Code::STORE_IC, Code::NORMAL, strict_mode);
493  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
494  if (probe->IsCode()) return Handle<Code>::cast(probe);
495 
496  StoreStubCompiler compiler(isolate_, strict_mode);
497  Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
498  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
499  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
500  JSObject::UpdateMapCodeCache(receiver, name, code);
501  return code;
502 }
503 
504 
505 Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name,
506  Handle<JSObject> receiver,
507  Handle<JSObject> holder,
508  Handle<AccessorInfo> callback,
509  StrictModeFlag strict_mode) {
510  ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
511  Code::Flags flags = Code::ComputeMonomorphicFlags(
512  Code::STORE_IC, Code::CALLBACKS, strict_mode);
513  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
514  if (probe->IsCode()) return Handle<Code>::cast(probe);
515 
516  StoreStubCompiler compiler(isolate_, strict_mode);
518  compiler.CompileStoreCallback(name, receiver, holder, callback);
519  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
520  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
521  JSObject::UpdateMapCodeCache(receiver, name, code);
522  return code;
523 }
524 
525 
526 Handle<Code> StubCache::ComputeStoreViaSetter(Handle<String> name,
527  Handle<JSObject> receiver,
528  Handle<JSObject> holder,
529  Handle<JSFunction> setter,
530  StrictModeFlag strict_mode) {
531  Code::Flags flags = Code::ComputeMonomorphicFlags(
532  Code::STORE_IC, Code::CALLBACKS, strict_mode);
533  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
534  if (probe->IsCode()) return Handle<Code>::cast(probe);
535 
536  StoreStubCompiler compiler(isolate_, strict_mode);
538  compiler.CompileStoreViaSetter(name, receiver, holder, setter);
539  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
540  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
541  JSObject::UpdateMapCodeCache(receiver, name, code);
542  return code;
543 }
544 
545 
546 Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
547  Handle<JSObject> receiver,
548  StrictModeFlag strict_mode) {
549  Code::Flags flags = Code::ComputeMonomorphicFlags(
550  Code::STORE_IC, Code::INTERCEPTOR, strict_mode);
551  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
552  if (probe->IsCode()) return Handle<Code>::cast(probe);
553 
554  StoreStubCompiler compiler(isolate_, strict_mode);
555  Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
556  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
557  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
558  JSObject::UpdateMapCodeCache(receiver, name, code);
559  return code;
560 }
561 
562 Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name,
563  Handle<JSObject> receiver,
564  int field_index,
565  Handle<Map> transition,
566  StrictModeFlag strict_mode) {
567  Code::StubType type =
568  (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
569  Code::Flags flags = Code::ComputeMonomorphicFlags(
570  Code::KEYED_STORE_IC, type, strict_mode);
571  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
572  if (probe->IsCode()) return Handle<Code>::cast(probe);
573 
574  KeyedStoreStubCompiler compiler(isolate(), strict_mode,
577  compiler.CompileStoreField(receiver, field_index, transition, name);
578  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
579  GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
580  JSObject::UpdateMapCodeCache(receiver, name, code);
581  return code;
582 }
583 
584 
585 #define CALL_LOGGER_TAG(kind, type) \
586  (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
587 
588 Handle<Code> StubCache::ComputeCallConstant(int argc,
589  Code::Kind kind,
590  Code::ExtraICState extra_state,
591  Handle<String> name,
592  Handle<Object> object,
593  Handle<JSObject> holder,
594  Handle<JSFunction> function) {
595  // Compute the check type and the map.
596  InlineCacheHolderFlag cache_holder =
597  IC::GetCodeCacheForObject(*object, *holder);
598  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
599 
600  // Compute check type based on receiver/holder.
602  if (object->IsString()) {
603  check = STRING_CHECK;
604  } else if (object->IsNumber()) {
605  check = NUMBER_CHECK;
606  } else if (object->IsBoolean()) {
607  check = BOOLEAN_CHECK;
608  }
609 
611  Code::ComputeMonomorphicFlags(kind, Code::CONSTANT_FUNCTION, extra_state,
612  cache_holder, argc);
613  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
614  if (probe->IsCode()) return Handle<Code>::cast(probe);
615 
616  CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
618  compiler.CompileCallConstant(object, holder, function, name, check);
619  code->set_check_type(check);
620  ASSERT_EQ(flags, code->flags());
621  PROFILE(isolate_,
622  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
623  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
624  JSObject::UpdateMapCodeCache(map_holder, name, code);
625  return code;
626 }
627 
628 
629 Handle<Code> StubCache::ComputeCallField(int argc,
630  Code::Kind kind,
631  Code::ExtraICState extra_state,
632  Handle<String> name,
633  Handle<Object> object,
634  Handle<JSObject> holder,
635  int index) {
636  // Compute the check type and the map.
637  InlineCacheHolderFlag cache_holder =
638  IC::GetCodeCacheForObject(*object, *holder);
639  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
640 
641  // TODO(1233596): We cannot do receiver map check for non-JS objects
642  // because they may be represented as immediates without a
643  // map. Instead, we check against the map in the holder.
644  if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
645  object = holder;
646  }
647 
649  Code::ComputeMonomorphicFlags(kind, Code::FIELD, extra_state,
650  cache_holder, argc);
651  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
652  if (probe->IsCode()) return Handle<Code>::cast(probe);
653 
654  CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
656  compiler.CompileCallField(Handle<JSObject>::cast(object),
657  holder, index, name);
658  ASSERT_EQ(flags, code->flags());
659  PROFILE(isolate_,
660  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
661  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
662  JSObject::UpdateMapCodeCache(map_holder, name, code);
663  return code;
664 }
665 
666 
667 Handle<Code> StubCache::ComputeCallInterceptor(int argc,
668  Code::Kind kind,
669  Code::ExtraICState extra_state,
670  Handle<String> name,
671  Handle<Object> object,
672  Handle<JSObject> holder) {
673  // Compute the check type and the map.
674  InlineCacheHolderFlag cache_holder =
675  IC::GetCodeCacheForObject(*object, *holder);
676  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
677 
678  // TODO(1233596): We cannot do receiver map check for non-JS objects
679  // because they may be represented as immediates without a
680  // map. Instead, we check against the map in the holder.
681  if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
682  object = holder;
683  }
684 
686  Code::ComputeMonomorphicFlags(kind, Code::INTERCEPTOR, extra_state,
687  cache_holder, argc);
688  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
689  if (probe->IsCode()) return Handle<Code>::cast(probe);
690 
691  CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
694  holder, name);
695  ASSERT_EQ(flags, code->flags());
696  PROFILE(isolate(),
697  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
698  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
699  JSObject::UpdateMapCodeCache(map_holder, name, code);
700  return code;
701 }
702 
703 
704 Handle<Code> StubCache::ComputeCallGlobal(int argc,
705  Code::Kind kind,
706  Code::ExtraICState extra_state,
707  Handle<String> name,
708  Handle<JSObject> receiver,
709  Handle<GlobalObject> holder,
711  Handle<JSFunction> function) {
712  InlineCacheHolderFlag cache_holder =
713  IC::GetCodeCacheForObject(*receiver, *holder);
714  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
716  Code::ComputeMonomorphicFlags(kind, Code::NORMAL, extra_state,
717  cache_holder, argc);
718  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
719  if (probe->IsCode()) return Handle<Code>::cast(probe);
720 
721  CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
723  compiler.CompileCallGlobal(receiver, holder, cell, function, name);
724  ASSERT_EQ(flags, code->flags());
725  PROFILE(isolate(),
726  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
727  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
728  JSObject::UpdateMapCodeCache(map_holder, name, code);
729  return code;
730 }
731 
732 
733 static void FillCache(Isolate* isolate, Handle<Code> code) {
735  UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
736  code->flags(),
737  code);
738  isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
739 }
740 
741 
742 Code* StubCache::FindCallInitialize(int argc,
743  RelocInfo::Mode mode,
744  Code::Kind kind) {
745  Code::ExtraICState extra_state =
746  CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
747  CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
749  Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
750 
751  // Use raw_unchecked... so we don't get assert failures during GC.
752  UnseededNumberDictionary* dictionary =
753  isolate()->heap()->raw_unchecked_non_monomorphic_cache();
754  int entry = dictionary->FindEntry(isolate(), flags);
755  ASSERT(entry != -1);
756  Object* code = dictionary->ValueAt(entry);
757  // This might be called during the marking phase of the collector
758  // hence the unchecked cast.
759  return reinterpret_cast<Code*>(code);
760 }
761 
762 
763 Handle<Code> StubCache::ComputeCallInitialize(int argc,
764  RelocInfo::Mode mode,
765  Code::Kind kind) {
766  Code::ExtraICState extra_state =
767  CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
768  CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
770  Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
772  isolate_->factory()->non_monomorphic_cache();
773  int entry = cache->FindEntry(isolate_, flags);
774  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
775 
776  StubCompiler compiler(isolate_);
777  Handle<Code> code = compiler.CompileCallInitialize(flags);
778  FillCache(isolate_, code);
779  return code;
780 }
781 
782 
783 Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
784  return ComputeCallInitialize(argc, mode, Code::CALL_IC);
785 }
786 
787 
788 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
789  return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
790  Code::KEYED_CALL_IC);
791 }
792 
793 
794 Handle<Code> StubCache::ComputeCallPreMonomorphic(
795  int argc,
796  Code::Kind kind,
797  Code::ExtraICState extra_state) {
798  Code::Flags flags =
799  Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
801  isolate_->factory()->non_monomorphic_cache();
802  int entry = cache->FindEntry(isolate_, flags);
803  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
804 
805  StubCompiler compiler(isolate_);
806  Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
807  FillCache(isolate_, code);
808  return code;
809 }
810 
811 
812 Handle<Code> StubCache::ComputeCallNormal(int argc,
813  Code::Kind kind,
814  Code::ExtraICState extra_state) {
815  Code::Flags flags =
816  Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
818  isolate_->factory()->non_monomorphic_cache();
819  int entry = cache->FindEntry(isolate_, flags);
820  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
821 
822  StubCompiler compiler(isolate_);
823  Handle<Code> code = compiler.CompileCallNormal(flags);
824  FillCache(isolate_, code);
825  return code;
826 }
827 
828 
829 Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
830  ASSERT(kind == Code::KEYED_CALL_IC);
831  Code::Flags flags =
832  Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState,
833  Code::NORMAL, argc);
835  isolate_->factory()->non_monomorphic_cache();
836  int entry = cache->FindEntry(isolate_, flags);
837  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
838 
839  StubCompiler compiler(isolate_);
840  Handle<Code> code = compiler.CompileCallArguments(flags);
841  FillCache(isolate_, code);
842  return code;
843 }
844 
845 
846 Handle<Code> StubCache::ComputeCallMegamorphic(
847  int argc,
848  Code::Kind kind,
849  Code::ExtraICState extra_state) {
850  Code::Flags flags =
851  Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
852  Code::NORMAL, argc);
854  isolate_->factory()->non_monomorphic_cache();
855  int entry = cache->FindEntry(isolate_, flags);
856  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
857 
858  StubCompiler compiler(isolate_);
859  Handle<Code> code = compiler.CompileCallMegamorphic(flags);
860  FillCache(isolate_, code);
861  return code;
862 }
863 
864 
865 Handle<Code> StubCache::ComputeCallMiss(int argc,
866  Code::Kind kind,
867  Code::ExtraICState extra_state) {
868  // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
869  // and monomorphic stubs are not mixed up together in the stub cache.
870  Code::Flags flags =
871  Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
872  Code::NORMAL, argc, OWN_MAP);
874  isolate_->factory()->non_monomorphic_cache();
875  int entry = cache->FindEntry(isolate_, flags);
876  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
877 
878  StubCompiler compiler(isolate_);
879  Handle<Code> code = compiler.CompileCallMiss(flags);
880  FillCache(isolate_, code);
881  return code;
882 }
883 
884 
885 #ifdef ENABLE_DEBUGGER_SUPPORT
886 Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
887  Code::Kind kind) {
888  // Extra IC state is irrelevant for debug break ICs. They jump to
889  // the actual call ic to carry out the work.
890  Code::Flags flags =
891  Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState,
892  Code::NORMAL, argc);
894  isolate_->factory()->non_monomorphic_cache();
895  int entry = cache->FindEntry(isolate_, flags);
896  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
897 
898  StubCompiler compiler(isolate_);
899  Handle<Code> code = compiler.CompileCallDebugBreak(flags);
900  FillCache(isolate_, code);
901  return code;
902 }
903 
904 
905 Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
906  Code::Kind kind) {
907  // Extra IC state is irrelevant for debug break ICs. They jump to
908  // the actual call ic to carry out the work.
909  Code::Flags flags =
910  Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState,
911  Code::NORMAL, argc);
913  isolate_->factory()->non_monomorphic_cache();
914  int entry = cache->FindEntry(isolate_, flags);
915  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
916 
917  StubCompiler compiler(isolate_);
918  Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
919  FillCache(isolate_, code);
920  return code;
921 }
922 #endif
923 
924 
925 void StubCache::Clear() {
926  Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
927  for (int i = 0; i < kPrimaryTableSize; i++) {
928  primary_[i].key = heap()->empty_string();
929  primary_[i].value = empty;
930  }
931  for (int j = 0; j < kSecondaryTableSize; j++) {
932  secondary_[j].key = heap()->empty_string();
933  secondary_[j].value = empty;
934  }
935 }
936 
937 
938 void StubCache::CollectMatchingMaps(SmallMapList* types,
939  String* name,
940  Code::Flags flags,
941  Handle<Context> native_context,
942  Zone* zone) {
943  for (int i = 0; i < kPrimaryTableSize; i++) {
944  if (primary_[i].key == name) {
945  Map* map = primary_[i].value->FindFirstMap();
946  // Map can be NULL, if the stub is constant function call
947  // with a primitive receiver.
948  if (map == NULL) continue;
949 
950  int offset = PrimaryOffset(name, flags, map);
951  if (entry(primary_, offset) == &primary_[i] &&
952  !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
953  types->Add(Handle<Map>(map), zone);
954  }
955  }
956  }
957 
958  for (int i = 0; i < kSecondaryTableSize; i++) {
959  if (secondary_[i].key == name) {
960  Map* map = secondary_[i].value->FindFirstMap();
961  // Map can be NULL, if the stub is constant function call
962  // with a primitive receiver.
963  if (map == NULL) continue;
964 
965  // Lookup in primary table and skip duplicates.
966  int primary_offset = PrimaryOffset(name, flags, map);
967  Entry* primary_entry = entry(primary_, primary_offset);
968  if (primary_entry->key == name) {
969  Map* primary_map = primary_entry->value->FindFirstMap();
970  if (map == primary_map) continue;
971  }
972 
973  // Lookup in secondary table and add matches.
974  int offset = SecondaryOffset(name, flags, primary_offset);
975  if (entry(secondary_, offset) == &secondary_[i] &&
976  !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
977  types->Add(Handle<Map>(map), zone);
978  }
979  }
980  }
981 }
982 
983 
984 // ------------------------------------------------------------------------
985 // StubCompiler implementation.
986 
987 
988 RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
989  ASSERT(args[0]->IsJSObject());
990  ASSERT(args[1]->IsJSObject());
991  ASSERT(args[3]->IsSmi());
992  AccessorInfo* callback = AccessorInfo::cast(args[4]);
993  Address getter_address = v8::ToCData<Address>(callback->getter());
994  v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
995  ASSERT(fun != NULL);
996  ASSERT(callback->IsCompatibleReceiver(args[0]));
997  v8::AccessorInfo info(&args[0]);
998  HandleScope scope(isolate);
999  v8::Handle<v8::Value> result;
1000  {
1001  // Leaving JavaScript.
1002  VMState state(isolate, EXTERNAL);
1003  ExternalCallbackScope call_scope(isolate, getter_address);
1004  result = fun(v8::Utils::ToLocal(args.at<String>(5)), info);
1005  }
1007  if (result.IsEmpty()) return HEAP->undefined_value();
1008  Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
1009  result_internal->VerifyApiCallResultType();
1010  return *result_internal;
1011 }
1012 
1013 
1014 RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
1015  JSObject* recv = JSObject::cast(args[0]);
1016  AccessorInfo* callback = AccessorInfo::cast(args[1]);
1017  Address setter_address = v8::ToCData<Address>(callback->setter());
1018  v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
1019  ASSERT(fun != NULL);
1020  ASSERT(callback->IsCompatibleReceiver(recv));
1021  Handle<String> name = args.at<String>(2);
1022  Handle<Object> value = args.at<Object>(3);
1023  HandleScope scope(isolate);
1024  LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1025  CustomArguments custom_args(isolate, callback->data(), recv, recv);
1026  v8::AccessorInfo info(custom_args.end());
1027  {
1028  // Leaving JavaScript.
1029  VMState state(isolate, EXTERNAL);
1030  ExternalCallbackScope call_scope(isolate, setter_address);
1031  fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1032  }
1034  return *value;
1035 }
1036 
1037 
1038 static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1039 
1040 
1048 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
1049  Handle<String> name_handle = args.at<String>(0);
1050  Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1051  ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1052  ASSERT(args[2]->IsJSObject()); // Receiver.
1053  ASSERT(args[3]->IsJSObject()); // Holder.
1054  ASSERT(args[5]->IsSmi()); // Isolate.
1055  ASSERT(args.length() == 6);
1056 
1057  Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1058  v8::NamedPropertyGetter getter =
1059  FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1060  ASSERT(getter != NULL);
1061 
1062  {
1063  // Use the interceptor getter.
1064  v8::AccessorInfo info(args.arguments() -
1065  kAccessorInfoOffsetInInterceptorArgs);
1066  HandleScope scope(isolate);
1068  {
1069  // Leaving JavaScript.
1070  VMState state(isolate, EXTERNAL);
1071  r = getter(v8::Utils::ToLocal(name_handle), info);
1072  }
1074  if (!r.IsEmpty()) {
1075  Handle<Object> result = v8::Utils::OpenHandle(*r);
1076  result->VerifyApiCallResultType();
1077  return *v8::Utils::OpenHandle(*r);
1078  }
1079  }
1080 
1081  return isolate->heap()->no_interceptor_result_sentinel();
1082 }
1083 
1084 
1085 static MaybeObject* ThrowReferenceError(String* name) {
1086  // If the load is non-contextual, just return the undefined result.
1087  // Note that both keyed and non-keyed loads may end up here, so we
1088  // can't use either LoadIC or KeyedLoadIC constructors.
1089  IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
1090  ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
1091  if (!ic.SlowIsContextual()) return HEAP->undefined_value();
1092 
1093  // Throw a reference error.
1094  HandleScope scope;
1095  Handle<String> name_handle(name);
1096  Handle<Object> error =
1097  FACTORY->NewReferenceError("not_defined",
1098  HandleVector(&name_handle, 1));
1099  return Isolate::Current()->Throw(*error);
1100 }
1101 
1102 
1103 static MaybeObject* LoadWithInterceptor(Arguments* args,
1104  PropertyAttributes* attrs) {
1105  Handle<String> name_handle = args->at<String>(0);
1106  Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1107  ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1108  Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1109  Handle<JSObject> holder_handle = args->at<JSObject>(3);
1110  ASSERT(args->length() == 6);
1111 
1112  Isolate* isolate = receiver_handle->GetIsolate();
1113 
1114  Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1115  v8::NamedPropertyGetter getter =
1116  FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1117  ASSERT(getter != NULL);
1118 
1119  {
1120  // Use the interceptor getter.
1121  v8::AccessorInfo info(args->arguments() -
1122  kAccessorInfoOffsetInInterceptorArgs);
1123  HandleScope scope(isolate);
1125  {
1126  // Leaving JavaScript.
1127  VMState state(isolate, EXTERNAL);
1128  r = getter(v8::Utils::ToLocal(name_handle), info);
1129  }
1131  if (!r.IsEmpty()) {
1132  *attrs = NONE;
1133  Handle<Object> result = v8::Utils::OpenHandle(*r);
1134  result->VerifyApiCallResultType();
1135  return *result;
1136  }
1137  }
1138 
1139  MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
1140  *receiver_handle,
1141  *name_handle,
1142  attrs);
1144  return result;
1145 }
1146 
1147 
1152 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
1153  PropertyAttributes attr = NONE;
1154  Object* result;
1155  { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1156  if (!maybe_result->ToObject(&result)) return maybe_result;
1157  }
1158 
1159  // If the property is present, return it.
1160  if (attr != ABSENT) return result;
1161  return ThrowReferenceError(String::cast(args[0]));
1162 }
1163 
1164 
1165 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
1166  PropertyAttributes attr;
1167  MaybeObject* result = LoadWithInterceptor(&args, &attr);
1169  // This is call IC. In this case, we simply return the undefined result which
1170  // will lead to an exception when trying to invoke the result as a
1171  // function.
1172  return result;
1173 }
1174 
1175 
1176 RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
1177  ASSERT(args.length() == 4);
1178  JSObject* recv = JSObject::cast(args[0]);
1179  String* name = String::cast(args[1]);
1180  Object* value = args[2];
1181  ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
1182  StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
1183  ASSERT(recv->HasNamedInterceptor());
1184  PropertyAttributes attr = NONE;
1185  MaybeObject* result = recv->SetPropertyWithInterceptor(
1186  name, value, attr, strict_mode);
1187  return result;
1188 }
1189 
1190 
1191 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
1192  JSObject* receiver = JSObject::cast(args[0]);
1193  ASSERT(args.smi_at(1) >= 0);
1194  uint32_t index = args.smi_at(1);
1195  return receiver->GetElementWithInterceptor(receiver, index);
1196 }
1197 
1198 
1199 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
1200  int argc = Code::ExtractArgumentsCountFromFlags(flags);
1201  Code::Kind kind = Code::ExtractKindFromFlags(flags);
1202  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1203  if (kind == Code::CALL_IC) {
1204  CallIC::GenerateInitialize(masm(), argc, extra_state);
1205  } else {
1206  KeyedCallIC::GenerateInitialize(masm(), argc);
1207  }
1208  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
1209  isolate()->counters()->call_initialize_stubs()->Increment();
1210  PROFILE(isolate(),
1211  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
1212  *code, code->arguments_count()));
1213  GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1214  return code;
1215 }
1216 
1217 
1218 Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
1219  int argc = Code::ExtractArgumentsCountFromFlags(flags);
1220  // The code of the PreMonomorphic stub is the same as the code
1221  // of the Initialized stub. They just differ on the code object flags.
1222  Code::Kind kind = Code::ExtractKindFromFlags(flags);
1223  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1224  if (kind == Code::CALL_IC) {
1225  CallIC::GenerateInitialize(masm(), argc, extra_state);
1226  } else {
1227  KeyedCallIC::GenerateInitialize(masm(), argc);
1228  }
1229  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1230  isolate()->counters()->call_premonomorphic_stubs()->Increment();
1231  PROFILE(isolate(),
1232  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
1233  *code, code->arguments_count()));
1234  GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1235  return code;
1236 }
1237 
1238 
1239 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
1240  int argc = Code::ExtractArgumentsCountFromFlags(flags);
1241  Code::Kind kind = Code::ExtractKindFromFlags(flags);
1242  if (kind == Code::CALL_IC) {
1243  // Call normal is always with a explict receiver.
1244  ASSERT(!CallIC::Contextual::decode(
1245  Code::ExtractExtraICStateFromFlags(flags)));
1246  CallIC::GenerateNormal(masm(), argc);
1247  } else {
1248  KeyedCallIC::GenerateNormal(masm(), argc);
1249  }
1250  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
1251  isolate()->counters()->call_normal_stubs()->Increment();
1252  PROFILE(isolate(),
1253  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
1254  *code, code->arguments_count()));
1255  GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1256  return code;
1257 }
1258 
1259 
1260 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
1261  int argc = Code::ExtractArgumentsCountFromFlags(flags);
1262  Code::Kind kind = Code::ExtractKindFromFlags(flags);
1263  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1264  if (kind == Code::CALL_IC) {
1265  CallIC::GenerateMegamorphic(masm(), argc, extra_state);
1266  } else {
1267  KeyedCallIC::GenerateMegamorphic(masm(), argc);
1268  }
1269  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
1270  isolate()->counters()->call_megamorphic_stubs()->Increment();
1271  PROFILE(isolate(),
1272  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1273  *code, code->arguments_count()));
1274  GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1275  return code;
1276 }
1277 
1278 
1279 Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
1280  int argc = Code::ExtractArgumentsCountFromFlags(flags);
1281  KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
1282  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
1283  PROFILE(isolate(),
1284  CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1285  CALL_MEGAMORPHIC_TAG),
1286  *code, code->arguments_count()));
1287  GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1288  return code;
1289 }
1290 
1291 
1292 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
1293  int argc = Code::ExtractArgumentsCountFromFlags(flags);
1294  Code::Kind kind = Code::ExtractKindFromFlags(flags);
1295  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1296  if (kind == Code::CALL_IC) {
1297  CallIC::GenerateMiss(masm(), argc, extra_state);
1298  } else {
1299  KeyedCallIC::GenerateMiss(masm(), argc);
1300  }
1301  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
1302  isolate()->counters()->call_megamorphic_stubs()->Increment();
1303  PROFILE(isolate(),
1304  CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
1305  *code, code->arguments_count()));
1306  GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1307  return code;
1308 }
1309 
1310 
1311 #ifdef ENABLE_DEBUGGER_SUPPORT
1312 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
1313  Debug::GenerateCallICDebugBreak(masm());
1314  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
1315  PROFILE(isolate(),
1316  CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1317  CALL_DEBUG_BREAK_TAG),
1318  *code, code->arguments_count()));
1319  return code;
1320 }
1321 
1322 
1323 Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1324  // Use the same code for the the step in preparations as we do for the
1325  // miss case.
1326  int argc = Code::ExtractArgumentsCountFromFlags(flags);
1327  Code::Kind kind = Code::ExtractKindFromFlags(flags);
1328  if (kind == Code::CALL_IC) {
1329  // For the debugger extra ic state is irrelevant.
1330  CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
1331  } else {
1332  KeyedCallIC::GenerateMiss(masm(), argc);
1333  }
1334  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1335  PROFILE(isolate(),
1336  CodeCreateEvent(
1337  CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1338  *code,
1339  code->arguments_count()));
1340  return code;
1341 }
1342 #endif // ENABLE_DEBUGGER_SUPPORT
1343 
1344 #undef CALL_LOGGER_TAG
1345 
1346 
1347 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1348  const char* name) {
1349  // Create code object in the heap.
1350  CodeDesc desc;
1351  masm_.GetCode(&desc);
1352  Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
1353 #ifdef ENABLE_DISASSEMBLER
1354  if (FLAG_print_code_stubs) code->Disassemble(name);
1355 #endif
1356  return code;
1357 }
1358 
1359 
1360 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1361  Handle<String> name) {
1362  return (FLAG_print_code_stubs && !name.is_null())
1363  ? GetCodeWithFlags(flags, *name->ToCString())
1364  : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1365 }
1366 
1367 
1368 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
1369  Handle<String> name,
1370  LookupResult* lookup) {
1371  holder->LocalLookupRealNamedProperty(*name, lookup);
1372  if (lookup->IsFound()) return;
1373  if (holder->GetPrototype()->IsNull()) return;
1374  holder->GetPrototype()->Lookup(*name, lookup);
1375 }
1376 
1377 
1378 Handle<Code> LoadStubCompiler::GetCode(Code::StubType type,
1379  Handle<String> name) {
1380  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
1381  Handle<Code> code = GetCodeWithFlags(flags, name);
1382  PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
1383  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1384  return code;
1385 }
1386 
1387 
1388 Handle<Code> KeyedLoadStubCompiler::GetCode(Code::StubType type,
1389  Handle<String> name,
1390  InlineCacheState state) {
1391  Code::Flags flags = Code::ComputeFlags(
1392  Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
1393  Handle<Code> code = GetCodeWithFlags(flags, name);
1394  PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
1395  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1396  return code;
1397 }
1398 
1399 
1400 Handle<Code> StoreStubCompiler::GetCode(Code::StubType type,
1401  Handle<String> name) {
1402  Code::Flags flags =
1403  Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
1404  Handle<Code> code = GetCodeWithFlags(flags, name);
1405  PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
1406  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
1407  return code;
1408 }
1409 
1410 
1411 Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type,
1412  Handle<String> name,
1413  InlineCacheState state) {
1414  Code::ExtraICState extra_state =
1415  Code::ComputeExtraICState(grow_mode_, strict_mode_);
1416  Code::Flags flags =
1417  Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type);
1418  Handle<Code> code = GetCodeWithFlags(flags, name);
1419  PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
1420  GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
1421  return code;
1422 }
1423 
1424 
1425 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1426  MacroAssembler* masm) {
1427  KeyedStoreIC::GenerateSlow(masm);
1428 }
1429 
1430 
1431 CallStubCompiler::CallStubCompiler(Isolate* isolate,
1432  int argc,
1433  Code::Kind kind,
1434  Code::ExtraICState extra_state,
1435  InlineCacheHolderFlag cache_holder)
1436  : StubCompiler(isolate),
1437  arguments_(argc),
1438  kind_(kind),
1439  extra_state_(extra_state),
1440  cache_holder_(cache_holder) {
1441 }
1442 
1443 
1445  if (function->shared()->HasBuiltinFunctionId()) {
1446  BuiltinFunctionId id = function->shared()->builtin_function_id();
1447 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
1449 #undef CALL_GENERATOR_CASE
1450  }
1451 
1452  CallOptimization optimization(function);
1453  return optimization.is_simple_api_call();
1454 }
1455 
1456 
1457 Handle<Code> CallStubCompiler::CompileCustomCall(
1458  Handle<Object> object,
1459  Handle<JSObject> holder,
1461  Handle<JSFunction> function,
1462  Handle<String> fname) {
1463  ASSERT(HasCustomCallGenerator(function));
1464 
1465  if (function->shared()->HasBuiltinFunctionId()) {
1466  BuiltinFunctionId id = function->shared()->builtin_function_id();
1467 #define CALL_GENERATOR_CASE(name) \
1468  if (id == k##name) { \
1469  return CallStubCompiler::Compile##name##Call(object, \
1470  holder, \
1471  cell, \
1472  function, \
1473  fname); \
1474  }
1476 #undef CALL_GENERATOR_CASE
1477  }
1478  CallOptimization optimization(function);
1479  ASSERT(optimization.is_simple_api_call());
1480  return CompileFastApiCall(optimization,
1481  object,
1482  holder,
1483  cell,
1484  function,
1485  fname);
1486 }
1487 
1488 
1489 Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
1490  Handle<String> name) {
1491  int argc = arguments_.immediate();
1493  type,
1494  extra_state_,
1495  cache_holder_,
1496  argc);
1497  return GetCodeWithFlags(flags, name);
1498 }
1499 
1500 
1501 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
1502  Handle<String> function_name;
1503  if (function->shared()->name()->IsString()) {
1504  function_name = Handle<String>(String::cast(function->shared()->name()));
1505  }
1506  return GetCode(Code::CONSTANT_FUNCTION, function_name);
1507 }
1508 
1509 
1510 Handle<Code> ConstructStubCompiler::GetCode() {
1511  Code::Flags flags = Code::ComputeFlags(Code::STUB);
1512  Handle<Code> code = GetCodeWithFlags(flags, "ConstructStub");
1513  PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, "ConstructStub"));
1514  GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", *code));
1515  return code;
1516 }
1517 
1518 
1519 CallOptimization::CallOptimization(LookupResult* lookup) {
1520  if (lookup->IsFound() &&
1521  lookup->IsCacheable() &&
1522  lookup->type() == CONSTANT_FUNCTION) {
1523  // We only optimize constant function calls.
1524  Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
1525  } else {
1526  Initialize(Handle<JSFunction>::null());
1527  }
1528 }
1529 
1530 CallOptimization::CallOptimization(Handle<JSFunction> function) {
1531  Initialize(function);
1532 }
1533 
1534 
1535 int CallOptimization::GetPrototypeDepthOfExpectedType(
1536  Handle<JSObject> object,
1537  Handle<JSObject> holder) const {
1538  ASSERT(is_simple_api_call());
1539  if (expected_receiver_type_.is_null()) return 0;
1540  int depth = 0;
1541  while (!object.is_identical_to(holder)) {
1542  if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
1543  object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
1544  ++depth;
1545  }
1546  if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
1547  return kInvalidProtoDepth;
1548 }
1549 
1550 
1551 void CallOptimization::Initialize(Handle<JSFunction> function) {
1552  constant_function_ = Handle<JSFunction>::null();
1553  is_simple_api_call_ = false;
1554  expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
1555  api_call_info_ = Handle<CallHandlerInfo>::null();
1556 
1557  if (function.is_null() || !function->is_compiled()) return;
1558 
1559  constant_function_ = function;
1560  AnalyzePossibleApiFunction(function);
1561 }
1562 
1563 
1564 void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
1565  if (!function->shared()->IsApiFunction()) return;
1566  Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
1567 
1568  // Require a C++ callback.
1569  if (info->call_code()->IsUndefined()) return;
1570  api_call_info_ =
1571  Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
1572 
1573  // Accept signatures that either have no restrictions at all or
1574  // only have restrictions on the receiver.
1575  if (!info->signature()->IsUndefined()) {
1576  Handle<SignatureInfo> signature =
1577  Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
1578  if (!signature->args()->IsUndefined()) return;
1579  if (!signature->receiver()->IsUndefined()) {
1580  expected_receiver_type_ =
1581  Handle<FunctionTemplateInfo>(
1582  FunctionTemplateInfo::cast(signature->receiver()));
1583  }
1584  }
1585 
1586  is_simple_api_call_ = true;
1587 }
1588 
1589 
1590 } } // namespace v8::internal
byte * Address
Definition: globals.h:157
MUST_USE_RESULT MaybeObject * GetElementWithInterceptor(Object *receiver, uint32_t index)
Definition: objects.cc:10179
Handle< Code > CompileLoadFunctionPrototype(Handle< String > name)
Handle< Code > CompileLoadCallback(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, Handle< AccessorInfo > callback)
static CallHandlerInfo * cast(Object *obj)
Handle< Code > CompileStoreField(Handle< JSObject > object, int index, Handle< Map > transition, Handle< String > name)
#define RETURN_IF_SCHEDULED_EXCEPTION(isolate)
Definition: isolate.h:112
Handle< Code > CompileLoadNonexistent(Handle< String > name, Handle< JSObject > object, Handle< JSObject > last)
static String * cast(Object *obj)
Handle< Code > CompileStoreElement(Handle< Map > receiver_map)
#define LOG(isolate, Call)
Definition: log.h:81
#define RUNTIME_FUNCTION(Type, Name)
Definition: arguments.h:121
String * key
Definition: stub-cache.h:70
#define CALL_GENERATOR_CASE(name)
#define ASSERT(condition)
Definition: checks.h:270
#define CUSTOM_CALL_IC_GENERATORS(V)
Definition: stub-cache.h:784
#define PROFILE(isolate, Call)
Definition: cpu-profiler.h:190
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
Factory * factory()
Definition: isolate.h:992
PropertyAttributes
Handle< Code > CompileLoadField(Handle< JSObject > object, Handle< JSObject > holder, int index, Handle< String > name)
Handle< Code > CompileStoreInterceptor(Handle< JSObject > object, Handle< String > name)
unsigned int seed
Definition: test-strings.cc:18
Handle< Code > CompileStoreField(Handle< JSObject > object, int index, Handle< Map > transition, Handle< String > name)
Object * ValueAt(int entry)
Definition: objects.h:3067
Handle< Code > CompileLoadInterceptor(Handle< JSObject > object, Handle< JSObject > holder, Handle< String > name)
Code * value
Definition: stub-cache.h:71
#define UNREACHABLE()
Definition: checks.h:50
Handle< Value >(* NamedPropertyGetter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:2053
Handle< Code > CompileCallGlobal(Handle< JSObject > object, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, Handle< JSFunction > function, Handle< String > name)
Handle< Code > CompileLoadField(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, int index)
Handle< Code > CompileStoreGlobal(Handle< GlobalObject > object, Handle< JSGlobalPropertyCell > holder, Handle< String > name)
Handle< Code > CompileLoadViaGetter(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > getter)
Handle< Code > CompileLoadConstant(Handle< JSObject > object, Handle< JSObject > holder, Handle< JSFunction > value, Handle< String > name)
Definition: stub-cache.h:69
Handle< Code > CompileLoadConstant(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, Handle< JSFunction > value)
Handle< Code > CompileCallField(Handle< JSObject > object, Handle< JSObject > holder, int index, Handle< String > name)
Map * map
Definition: stub-cache.h:72
Handle< Code > CompileLoadStringLength(Handle< String > name)
void(* AccessorSetter)(Local< String > property, Local< Value > value, const AccessorInfo &info)
Definition: v8.h:1452
static FunctionTemplateInfo * cast(Object *obj)
Handle< Code > CompileLoadGlobal(Handle< JSObject > object, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, Handle< String > name, bool is_dont_delete)
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, int argc=-1, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:3491
Handle< Code > CompileStoreCallback(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< AccessorInfo > callback)
Definition: v8.h:105
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
bool IsPowerOf2(T x)
Definition: utils.h:50
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
#define CALL_LOGGER_TAG(kind, type)
Definition: stub-cache.cc:585
#define GDBJIT(action)
Definition: gdb-jit.h:141
bool is_null() const
Definition: handles.h:87
Handle< Code > CompileCallInterceptor(Handle< JSObject > object, Handle< JSObject > holder, Handle< String > name)
static Handle< T > null()
Definition: handles.h:86
Map * FindFirstMap()
Definition: objects.cc:8401
#define HEAP
Definition: isolate.h:1433
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
Handle< Code > CompileLoadArrayLength(Handle< String > name)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
void public_set_non_monomorphic_cache(UnseededNumberDictionary *value)
Definition: heap.h:1241
Handle< Code > CompileCallConstant(Handle< Object > object, Handle< JSObject > holder, Handle< JSFunction > function, Handle< String > name, CheckType check)
bool IsCompatibleReceiver(Object *receiver)
Definition: objects-inl.h:5135
bool IsEmpty() const
Definition: v8.h:209
#define FACTORY
Definition: isolate.h:1434
static bool HasCustomCallGenerator(Handle< JSFunction > function)
Definition: stub-cache.cc:1444
const int kInvalidProtoDepth
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:117
Handle< Code > CompileLoadCallback(Handle< String > name, Handle< JSObject > object, Handle< JSObject > holder, Handle< AccessorInfo > callback)
#define STATIC_ASSERT(test)
Definition: checks.h:283
void Add(Handle< Map > handle, Zone *zone)
Definition: ast.h:274
static SignatureInfo * cast(Object *obj)
Handle< Code > CompileLoadInterceptor(Handle< JSObject > object, Handle< JSObject > holder, Handle< String > name)
KeyedAccessGrowMode
Definition: objects.h:142
void check(i::Vector< const char > string)
Handle< Value >(* AccessorGetter)(Local< String > property, const AccessorInfo &info)
Definition: v8.h:1448
Handle< Code > CompileLoadElement(Handle< Map > receiver_map)
Handle< Code > CompileStoreViaSetter(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > setter)
static JSObject * cast(Object *obj)
static Flags ComputeMonomorphicFlags(Kind kind, StubType type, ExtraICState extra_ic_state=kNoExtraICState, InlineCacheHolderFlag holder=OWN_MAP, int argc=-1)
Definition: objects-inl.h:3514