~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/third_party/v8/src/stub-cache.cc

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
121
  Code::Flags flags =
 
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_);
 
127
  Handle<Code> code =
 
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_);
 
146
  Handle<Code> code =
 
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);
 
161
  Code::Flags flags =
 
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_);
 
167
  Handle<Code> code =
 
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);
 
181
  Code::Flags flags =
 
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_);
 
187
  Handle<Code> code =
 
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);
 
201
  Code::Flags flags =
 
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_);
 
207
  Handle<Code> code =
 
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);
 
220
  Code::Flags flags =
 
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_);
 
226
  Handle<Code> code =
 
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,
 
243
                                          Handle<JSGlobalPropertyCell> cell,
 
244
                                          bool is_dont_delete) {
 
245
  ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
 
246
  Code::Flags flags =
 
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_);
 
252
  Handle<Code> code =
 
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);
 
266
  Code::Flags flags =
 
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_);
 
272
  Handle<Code> code =
 
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,
 
287
                                                    Code::CONSTANT_FUNCTION);
 
288
  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
 
289
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
290
 
 
291
  KeyedLoadStubCompiler compiler(isolate_);
 
292
  Handle<Code> code =
 
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);
 
305
  Code::Flags flags =
 
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);
 
325
  Code::Flags flags =
 
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_);
 
331
  Handle<Code> code =
 
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) {
 
342
  Code::Flags flags =
 
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) {
 
358
  Code::Flags flags =
 
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) {
 
376
  Code::Flags flags =
 
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_);
 
382
  Handle<Code> code = compiler.CompileLoadFunctionPrototype(name);
 
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);
 
403
  Handle<Code> code =
 
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);
 
420
  Code::Flags flags =
 
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
 
 
444
  Handle<Code> code;
 
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,
 
453
                                      ALLOW_JSARRAY_GROWTH);
 
454
      code = compiler.CompileStoreElement(receiver_map);
 
455
      break;
 
456
    }
 
457
    case KeyedIC::STORE_NO_TRANSITION: {
 
458
      KeyedStoreStubCompiler compiler(isolate_, strict_mode,
 
459
                                      DO_NOT_ALLOW_JSARRAY_GROWTH);
 
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,
 
489
                                           Handle<JSGlobalPropertyCell> cell,
 
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<AccessorInfo> callback,
 
508
                                             StrictModeFlag strict_mode) {
 
509
  ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
 
510
  Code::Flags flags = Code::ComputeMonomorphicFlags(
 
511
      Code::STORE_IC, Code::CALLBACKS, strict_mode);
 
512
  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
 
513
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
514
 
 
515
  StoreStubCompiler compiler(isolate_, strict_mode);
 
516
  Handle<Code> code = compiler.CompileStoreCallback(receiver, callback, name);
 
517
  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
 
518
  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
 
519
  JSObject::UpdateMapCodeCache(receiver, name, code);
 
520
  return code;
 
521
}
 
522
 
 
523
 
 
524
Handle<Code> StubCache::ComputeStoreViaSetter(Handle<String> name,
 
525
                                              Handle<JSObject> receiver,
 
526
                                              Handle<JSObject> holder,
 
527
                                              Handle<JSFunction> setter,
 
528
                                              StrictModeFlag strict_mode) {
 
529
  Code::Flags flags = Code::ComputeMonomorphicFlags(
 
530
      Code::STORE_IC, Code::CALLBACKS, strict_mode);
 
531
  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
 
532
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
533
 
 
534
  StoreStubCompiler compiler(isolate_, strict_mode);
 
535
  Handle<Code> code =
 
536
      compiler.CompileStoreViaSetter(name, receiver, holder, setter);
 
537
  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
 
538
  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
 
539
  JSObject::UpdateMapCodeCache(receiver, name, code);
 
540
  return code;
 
541
}
 
542
 
 
543
 
 
544
Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
 
545
                                                Handle<JSObject> receiver,
 
546
                                                StrictModeFlag strict_mode) {
 
547
  Code::Flags flags = Code::ComputeMonomorphicFlags(
 
548
      Code::STORE_IC, Code::INTERCEPTOR, strict_mode);
 
549
  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
 
550
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
551
 
 
552
  StoreStubCompiler compiler(isolate_, strict_mode);
 
553
  Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
 
554
  PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
 
555
  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
 
556
  JSObject::UpdateMapCodeCache(receiver, name, code);
 
557
  return code;
 
558
}
 
559
 
 
560
Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name,
 
561
                                               Handle<JSObject> receiver,
 
562
                                               int field_index,
 
563
                                               Handle<Map> transition,
 
564
                                               StrictModeFlag strict_mode) {
 
565
  Code::StubType type =
 
566
      (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
 
567
  Code::Flags flags = Code::ComputeMonomorphicFlags(
 
568
      Code::KEYED_STORE_IC, type, strict_mode);
 
569
  Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
 
570
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
571
 
 
572
  KeyedStoreStubCompiler compiler(isolate(), strict_mode,
 
573
                                  DO_NOT_ALLOW_JSARRAY_GROWTH);
 
574
  Handle<Code> code =
 
575
      compiler.CompileStoreField(receiver, field_index, transition, name);
 
576
  PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
 
577
  GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
 
578
  JSObject::UpdateMapCodeCache(receiver, name, code);
 
579
  return code;
 
580
}
 
581
 
 
582
 
 
583
#define CALL_LOGGER_TAG(kind, type) \
 
584
    (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
 
585
 
 
586
Handle<Code> StubCache::ComputeCallConstant(int argc,
 
587
                                            Code::Kind kind,
 
588
                                            Code::ExtraICState extra_state,
 
589
                                            Handle<String> name,
 
590
                                            Handle<Object> object,
 
591
                                            Handle<JSObject> holder,
 
592
                                            Handle<JSFunction> function) {
 
593
  // Compute the check type and the map.
 
594
  InlineCacheHolderFlag cache_holder =
 
595
      IC::GetCodeCacheForObject(*object, *holder);
 
596
  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
 
597
 
 
598
  // Compute check type based on receiver/holder.
 
599
  CheckType check = RECEIVER_MAP_CHECK;
 
600
  if (object->IsString()) {
 
601
    check = STRING_CHECK;
 
602
  } else if (object->IsNumber()) {
 
603
    check = NUMBER_CHECK;
 
604
  } else if (object->IsBoolean()) {
 
605
    check = BOOLEAN_CHECK;
 
606
  }
 
607
 
 
608
  Code::Flags flags =
 
609
      Code::ComputeMonomorphicFlags(kind, Code::CONSTANT_FUNCTION, extra_state,
 
610
                                    cache_holder, argc);
 
611
  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
 
612
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
613
 
 
614
  CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
 
615
  Handle<Code> code =
 
616
      compiler.CompileCallConstant(object, holder, function, name, check);
 
617
  code->set_check_type(check);
 
618
  ASSERT_EQ(flags, code->flags());
 
619
  PROFILE(isolate_,
 
620
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
 
621
  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
 
622
  JSObject::UpdateMapCodeCache(map_holder, name, code);
 
623
  return code;
 
624
}
 
625
 
 
626
 
 
627
Handle<Code> StubCache::ComputeCallField(int argc,
 
628
                                         Code::Kind kind,
 
629
                                         Code::ExtraICState extra_state,
 
630
                                         Handle<String> name,
 
631
                                         Handle<Object> object,
 
632
                                         Handle<JSObject> holder,
 
633
                                         int index) {
 
634
  // Compute the check type and the map.
 
635
  InlineCacheHolderFlag cache_holder =
 
636
      IC::GetCodeCacheForObject(*object, *holder);
 
637
  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
 
638
 
 
639
  // TODO(1233596): We cannot do receiver map check for non-JS objects
 
640
  // because they may be represented as immediates without a
 
641
  // map. Instead, we check against the map in the holder.
 
642
  if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
 
643
    object = holder;
 
644
  }
 
645
 
 
646
  Code::Flags flags =
 
647
      Code::ComputeMonomorphicFlags(kind, Code::FIELD, extra_state,
 
648
                                    cache_holder, argc);
 
649
  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
 
650
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
651
 
 
652
  CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
 
653
  Handle<Code> code =
 
654
      compiler.CompileCallField(Handle<JSObject>::cast(object),
 
655
                                holder, index, name);
 
656
  ASSERT_EQ(flags, code->flags());
 
657
  PROFILE(isolate_,
 
658
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
 
659
  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
 
660
  JSObject::UpdateMapCodeCache(map_holder, name, code);
 
661
  return code;
 
662
}
 
663
 
 
664
 
 
665
Handle<Code> StubCache::ComputeCallInterceptor(int argc,
 
666
                                               Code::Kind kind,
 
667
                                               Code::ExtraICState extra_state,
 
668
                                               Handle<String> name,
 
669
                                               Handle<Object> object,
 
670
                                               Handle<JSObject> holder) {
 
671
  // Compute the check type and the map.
 
672
  InlineCacheHolderFlag cache_holder =
 
673
      IC::GetCodeCacheForObject(*object, *holder);
 
674
  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
 
675
 
 
676
  // TODO(1233596): We cannot do receiver map check for non-JS objects
 
677
  // because they may be represented as immediates without a
 
678
  // map. Instead, we check against the map in the holder.
 
679
  if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
 
680
    object = holder;
 
681
  }
 
682
 
 
683
  Code::Flags flags =
 
684
      Code::ComputeMonomorphicFlags(kind, Code::INTERCEPTOR, extra_state,
 
685
                                    cache_holder, argc);
 
686
  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
 
687
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
688
 
 
689
  CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
 
690
  Handle<Code> code =
 
691
      compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
 
692
                                      holder, name);
 
693
  ASSERT_EQ(flags, code->flags());
 
694
  PROFILE(isolate(),
 
695
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
 
696
  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
 
697
  JSObject::UpdateMapCodeCache(map_holder, name, code);
 
698
  return code;
 
699
}
 
700
 
 
701
 
 
702
Handle<Code> StubCache::ComputeCallGlobal(int argc,
 
703
                                          Code::Kind kind,
 
704
                                          Code::ExtraICState extra_state,
 
705
                                          Handle<String> name,
 
706
                                          Handle<JSObject> receiver,
 
707
                                          Handle<GlobalObject> holder,
 
708
                                          Handle<JSGlobalPropertyCell> cell,
 
709
                                          Handle<JSFunction> function) {
 
710
  InlineCacheHolderFlag cache_holder =
 
711
      IC::GetCodeCacheForObject(*receiver, *holder);
 
712
  Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
 
713
  Code::Flags flags =
 
714
      Code::ComputeMonomorphicFlags(kind, Code::NORMAL, extra_state,
 
715
                                    cache_holder, argc);
 
716
  Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
 
717
  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
718
 
 
719
  CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
 
720
  Handle<Code> code =
 
721
      compiler.CompileCallGlobal(receiver, holder, cell, function, name);
 
722
  ASSERT_EQ(flags, code->flags());
 
723
  PROFILE(isolate(),
 
724
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
 
725
  GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
 
726
  JSObject::UpdateMapCodeCache(map_holder, name, code);
 
727
  return code;
 
728
}
 
729
 
 
730
 
 
731
static void FillCache(Isolate* isolate, Handle<Code> code) {
 
732
  Handle<UnseededNumberDictionary> dictionary =
 
733
      UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
 
734
                                    code->flags(),
 
735
                                    code);
 
736
  isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
 
737
}
 
738
 
 
739
 
 
740
Code* StubCache::FindCallInitialize(int argc,
 
741
                                    RelocInfo::Mode mode,
 
742
                                    Code::Kind kind) {
 
743
  Code::ExtraICState extra_state =
 
744
      CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
 
745
      CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
 
746
  Code::Flags flags =
 
747
      Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
 
748
 
 
749
  // Use raw_unchecked... so we don't get assert failures during GC.
 
750
  UnseededNumberDictionary* dictionary =
 
751
      isolate()->heap()->raw_unchecked_non_monomorphic_cache();
 
752
  int entry = dictionary->FindEntry(isolate(), flags);
 
753
  ASSERT(entry != -1);
 
754
  Object* code = dictionary->ValueAt(entry);
 
755
  // This might be called during the marking phase of the collector
 
756
  // hence the unchecked cast.
 
757
  return reinterpret_cast<Code*>(code);
 
758
}
 
759
 
 
760
 
 
761
Handle<Code> StubCache::ComputeCallInitialize(int argc,
 
762
                                              RelocInfo::Mode mode,
 
763
                                              Code::Kind kind) {
 
764
  Code::ExtraICState extra_state =
 
765
      CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
 
766
      CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
 
767
  Code::Flags flags =
 
768
      Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
 
769
  Handle<UnseededNumberDictionary> cache =
 
770
      isolate_->factory()->non_monomorphic_cache();
 
771
  int entry = cache->FindEntry(isolate_, flags);
 
772
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
773
 
 
774
  StubCompiler compiler(isolate_);
 
775
  Handle<Code> code = compiler.CompileCallInitialize(flags);
 
776
  FillCache(isolate_, code);
 
777
  return code;
 
778
}
 
779
 
 
780
 
 
781
Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
 
782
  return ComputeCallInitialize(argc, mode, Code::CALL_IC);
 
783
}
 
784
 
 
785
 
 
786
Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
 
787
  return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
 
788
                               Code::KEYED_CALL_IC);
 
789
}
 
790
 
 
791
 
 
792
Handle<Code> StubCache::ComputeCallPreMonomorphic(
 
793
    int argc,
 
794
    Code::Kind kind,
 
795
    Code::ExtraICState extra_state) {
 
796
  Code::Flags flags =
 
797
      Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
 
798
  Handle<UnseededNumberDictionary> cache =
 
799
      isolate_->factory()->non_monomorphic_cache();
 
800
  int entry = cache->FindEntry(isolate_, flags);
 
801
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
802
 
 
803
  StubCompiler compiler(isolate_);
 
804
  Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
 
805
  FillCache(isolate_, code);
 
806
  return code;
 
807
}
 
808
 
 
809
 
 
810
Handle<Code> StubCache::ComputeCallNormal(int argc,
 
811
                                          Code::Kind kind,
 
812
                                          Code::ExtraICState extra_state) {
 
813
  Code::Flags flags =
 
814
      Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
 
815
  Handle<UnseededNumberDictionary> cache =
 
816
      isolate_->factory()->non_monomorphic_cache();
 
817
  int entry = cache->FindEntry(isolate_, flags);
 
818
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
819
 
 
820
  StubCompiler compiler(isolate_);
 
821
  Handle<Code> code = compiler.CompileCallNormal(flags);
 
822
  FillCache(isolate_, code);
 
823
  return code;
 
824
}
 
825
 
 
826
 
 
827
Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
 
828
  ASSERT(kind == Code::KEYED_CALL_IC);
 
829
  Code::Flags flags =
 
830
      Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState,
 
831
                         Code::NORMAL, argc);
 
832
  Handle<UnseededNumberDictionary> cache =
 
833
      isolate_->factory()->non_monomorphic_cache();
 
834
  int entry = cache->FindEntry(isolate_, flags);
 
835
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
836
 
 
837
  StubCompiler compiler(isolate_);
 
838
  Handle<Code> code = compiler.CompileCallArguments(flags);
 
839
  FillCache(isolate_, code);
 
840
  return code;
 
841
}
 
842
 
 
843
 
 
844
Handle<Code> StubCache::ComputeCallMegamorphic(
 
845
    int argc,
 
846
    Code::Kind kind,
 
847
    Code::ExtraICState extra_state) {
 
848
  Code::Flags flags =
 
849
      Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
 
850
                         Code::NORMAL, argc);
 
851
  Handle<UnseededNumberDictionary> cache =
 
852
      isolate_->factory()->non_monomorphic_cache();
 
853
  int entry = cache->FindEntry(isolate_, flags);
 
854
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
855
 
 
856
  StubCompiler compiler(isolate_);
 
857
  Handle<Code> code = compiler.CompileCallMegamorphic(flags);
 
858
  FillCache(isolate_, code);
 
859
  return code;
 
860
}
 
861
 
 
862
 
 
863
Handle<Code> StubCache::ComputeCallMiss(int argc,
 
864
                                        Code::Kind kind,
 
865
                                        Code::ExtraICState extra_state) {
 
866
  // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
 
867
  // and monomorphic stubs are not mixed up together in the stub cache.
 
868
  Code::Flags flags =
 
869
      Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
 
870
                         Code::NORMAL, argc, OWN_MAP);
 
871
  Handle<UnseededNumberDictionary> cache =
 
872
      isolate_->factory()->non_monomorphic_cache();
 
873
  int entry = cache->FindEntry(isolate_, flags);
 
874
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
875
 
 
876
  StubCompiler compiler(isolate_);
 
877
  Handle<Code> code = compiler.CompileCallMiss(flags);
 
878
  FillCache(isolate_, code);
 
879
  return code;
 
880
}
 
881
 
 
882
 
 
883
#ifdef ENABLE_DEBUGGER_SUPPORT
 
884
Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
 
885
                                              Code::Kind kind) {
 
886
  // Extra IC state is irrelevant for debug break ICs. They jump to
 
887
  // the actual call ic to carry out the work.
 
888
  Code::Flags flags =
 
889
      Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState,
 
890
                         Code::NORMAL, argc);
 
891
  Handle<UnseededNumberDictionary> cache =
 
892
      isolate_->factory()->non_monomorphic_cache();
 
893
  int entry = cache->FindEntry(isolate_, flags);
 
894
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
895
 
 
896
  StubCompiler compiler(isolate_);
 
897
  Handle<Code> code = compiler.CompileCallDebugBreak(flags);
 
898
  FillCache(isolate_, code);
 
899
  return code;
 
900
}
 
901
 
 
902
 
 
903
Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
 
904
                                                      Code::Kind kind) {
 
905
  // Extra IC state is irrelevant for debug break ICs. They jump to
 
906
  // the actual call ic to carry out the work.
 
907
  Code::Flags flags =
 
908
      Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState,
 
909
                         Code::NORMAL, argc);
 
910
  Handle<UnseededNumberDictionary> cache =
 
911
      isolate_->factory()->non_monomorphic_cache();
 
912
  int entry = cache->FindEntry(isolate_, flags);
 
913
  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
 
914
 
 
915
  StubCompiler compiler(isolate_);
 
916
  Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
 
917
  FillCache(isolate_, code);
 
918
  return code;
 
919
}
 
920
#endif
 
921
 
 
922
 
 
923
void StubCache::Clear() {
 
924
  Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
 
925
  for (int i = 0; i < kPrimaryTableSize; i++) {
 
926
    primary_[i].key = heap()->empty_string();
 
927
    primary_[i].value = empty;
 
928
  }
 
929
  for (int j = 0; j < kSecondaryTableSize; j++) {
 
930
    secondary_[j].key = heap()->empty_string();
 
931
    secondary_[j].value = empty;
 
932
  }
 
933
}
 
934
 
 
935
 
 
936
void StubCache::CollectMatchingMaps(SmallMapList* types,
 
937
                                    String* name,
 
938
                                    Code::Flags flags,
 
939
                                    Handle<Context> global_context,
 
940
                                    Zone* zone) {
 
941
  for (int i = 0; i < kPrimaryTableSize; i++) {
 
942
    if (primary_[i].key == name) {
 
943
      Map* map = primary_[i].value->FindFirstMap();
 
944
      // Map can be NULL, if the stub is constant function call
 
945
      // with a primitive receiver.
 
946
      if (map == NULL) continue;
 
947
 
 
948
      int offset = PrimaryOffset(name, flags, map);
 
949
      if (entry(primary_, offset) == &primary_[i] &&
 
950
          !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
 
951
        types->Add(Handle<Map>(map), zone);
 
952
      }
 
953
    }
 
954
  }
 
955
 
 
956
  for (int i = 0; i < kSecondaryTableSize; i++) {
 
957
    if (secondary_[i].key == name) {
 
958
      Map* map = secondary_[i].value->FindFirstMap();
 
959
      // Map can be NULL, if the stub is constant function call
 
960
      // with a primitive receiver.
 
961
      if (map == NULL) continue;
 
962
 
 
963
      // Lookup in primary table and skip duplicates.
 
964
      int primary_offset = PrimaryOffset(name, flags, map);
 
965
      Entry* primary_entry = entry(primary_, primary_offset);
 
966
      if (primary_entry->key == name) {
 
967
        Map* primary_map = primary_entry->value->FindFirstMap();
 
968
        if (map == primary_map) continue;
 
969
      }
 
970
 
 
971
      // Lookup in secondary table and add matches.
 
972
      int offset = SecondaryOffset(name, flags, primary_offset);
 
973
      if (entry(secondary_, offset) == &secondary_[i] &&
 
974
          !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
 
975
        types->Add(Handle<Map>(map), zone);
 
976
      }
 
977
    }
 
978
  }
 
979
}
 
980
 
 
981
 
 
982
// ------------------------------------------------------------------------
 
983
// StubCompiler implementation.
 
984
 
 
985
 
 
986
RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
 
987
  ASSERT(args[0]->IsJSObject());
 
988
  ASSERT(args[1]->IsJSObject());
 
989
  ASSERT(args[3]->IsSmi());
 
990
  AccessorInfo* callback = AccessorInfo::cast(args[4]);
 
991
  Address getter_address = v8::ToCData<Address>(callback->getter());
 
992
  v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
 
993
  ASSERT(fun != NULL);
 
994
  ASSERT(callback->IsCompatibleReceiver(args[0]));
 
995
  v8::AccessorInfo info(&args[0]);
 
996
  HandleScope scope(isolate);
 
997
  v8::Handle<v8::Value> result;
 
998
  {
 
999
    // Leaving JavaScript.
 
1000
    VMState state(isolate, EXTERNAL);
 
1001
    ExternalCallbackScope call_scope(isolate, getter_address);
 
1002
    result = fun(v8::Utils::ToLocal(args.at<String>(5)), info);
 
1003
  }
 
1004
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
 
1005
  if (result.IsEmpty()) return HEAP->undefined_value();
 
1006
  return *v8::Utils::OpenHandle(*result);
 
1007
}
 
1008
 
 
1009
 
 
1010
RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
 
1011
  JSObject* recv = JSObject::cast(args[0]);
 
1012
  AccessorInfo* callback = AccessorInfo::cast(args[1]);
 
1013
  Address setter_address = v8::ToCData<Address>(callback->setter());
 
1014
  v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
 
1015
  ASSERT(fun != NULL);
 
1016
  ASSERT(callback->IsCompatibleReceiver(recv));
 
1017
  Handle<String> name = args.at<String>(2);
 
1018
  Handle<Object> value = args.at<Object>(3);
 
1019
  HandleScope scope(isolate);
 
1020
  LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
 
1021
  CustomArguments custom_args(isolate, callback->data(), recv, recv);
 
1022
  v8::AccessorInfo info(custom_args.end());
 
1023
  {
 
1024
    // Leaving JavaScript.
 
1025
    VMState state(isolate, EXTERNAL);
 
1026
    ExternalCallbackScope call_scope(isolate, setter_address);
 
1027
    fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
 
1028
  }
 
1029
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
 
1030
  return *value;
 
1031
}
 
1032
 
 
1033
 
 
1034
static const int kAccessorInfoOffsetInInterceptorArgs = 2;
 
1035
 
 
1036
 
 
1037
/**
 
1038
 * Attempts to load a property with an interceptor (which must be present),
 
1039
 * but doesn't search the prototype chain.
 
1040
 *
 
1041
 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
 
1042
 * provide any value for the given name.
 
1043
 */
 
1044
RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
 
1045
  Handle<String> name_handle = args.at<String>(0);
 
1046
  Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
 
1047
  ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
 
1048
  ASSERT(args[2]->IsJSObject());  // Receiver.
 
1049
  ASSERT(args[3]->IsJSObject());  // Holder.
 
1050
  ASSERT(args[5]->IsSmi());  // Isolate.
 
1051
  ASSERT(args.length() == 6);
 
1052
 
 
1053
  Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
 
1054
  v8::NamedPropertyGetter getter =
 
1055
      FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
 
1056
  ASSERT(getter != NULL);
 
1057
 
 
1058
  {
 
1059
    // Use the interceptor getter.
 
1060
    v8::AccessorInfo info(args.arguments() -
 
1061
                          kAccessorInfoOffsetInInterceptorArgs);
 
1062
    HandleScope scope(isolate);
 
1063
    v8::Handle<v8::Value> r;
 
1064
    {
 
1065
      // Leaving JavaScript.
 
1066
      VMState state(isolate, EXTERNAL);
 
1067
      r = getter(v8::Utils::ToLocal(name_handle), info);
 
1068
    }
 
1069
    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
 
1070
    if (!r.IsEmpty()) {
 
1071
      return *v8::Utils::OpenHandle(*r);
 
1072
    }
 
1073
  }
 
1074
 
 
1075
  return isolate->heap()->no_interceptor_result_sentinel();
 
1076
}
 
1077
 
 
1078
 
 
1079
static MaybeObject* ThrowReferenceError(String* name) {
 
1080
  // If the load is non-contextual, just return the undefined result.
 
1081
  // Note that both keyed and non-keyed loads may end up here, so we
 
1082
  // can't use either LoadIC or KeyedLoadIC constructors.
 
1083
  IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
 
1084
  ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
 
1085
  if (!ic.SlowIsContextual()) return HEAP->undefined_value();
 
1086
 
 
1087
  // Throw a reference error.
 
1088
  HandleScope scope;
 
1089
  Handle<String> name_handle(name);
 
1090
  Handle<Object> error =
 
1091
      FACTORY->NewReferenceError("not_defined",
 
1092
                                  HandleVector(&name_handle, 1));
 
1093
  return Isolate::Current()->Throw(*error);
 
1094
}
 
1095
 
 
1096
 
 
1097
static MaybeObject* LoadWithInterceptor(Arguments* args,
 
1098
                                        PropertyAttributes* attrs) {
 
1099
  Handle<String> name_handle = args->at<String>(0);
 
1100
  Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
 
1101
  ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
 
1102
  Handle<JSObject> receiver_handle = args->at<JSObject>(2);
 
1103
  Handle<JSObject> holder_handle = args->at<JSObject>(3);
 
1104
  ASSERT(args->length() == 6);
 
1105
 
 
1106
  Isolate* isolate = receiver_handle->GetIsolate();
 
1107
 
 
1108
  Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
 
1109
  v8::NamedPropertyGetter getter =
 
1110
      FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
 
1111
  ASSERT(getter != NULL);
 
1112
 
 
1113
  {
 
1114
    // Use the interceptor getter.
 
1115
    v8::AccessorInfo info(args->arguments() -
 
1116
                          kAccessorInfoOffsetInInterceptorArgs);
 
1117
    HandleScope scope(isolate);
 
1118
    v8::Handle<v8::Value> r;
 
1119
    {
 
1120
      // Leaving JavaScript.
 
1121
      VMState state(isolate, EXTERNAL);
 
1122
      r = getter(v8::Utils::ToLocal(name_handle), info);
 
1123
    }
 
1124
    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
 
1125
    if (!r.IsEmpty()) {
 
1126
      *attrs = NONE;
 
1127
      return *v8::Utils::OpenHandle(*r);
 
1128
    }
 
1129
  }
 
1130
 
 
1131
  MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
 
1132
      *receiver_handle,
 
1133
      *name_handle,
 
1134
      attrs);
 
1135
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
 
1136
  return result;
 
1137
}
 
1138
 
 
1139
 
 
1140
/**
 
1141
 * Loads a property with an interceptor performing post interceptor
 
1142
 * lookup if interceptor failed.
 
1143
 */
 
1144
RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
 
1145
  PropertyAttributes attr = NONE;
 
1146
  Object* result;
 
1147
  { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
 
1148
    if (!maybe_result->ToObject(&result)) return maybe_result;
 
1149
  }
 
1150
 
 
1151
  // If the property is present, return it.
 
1152
  if (attr != ABSENT) return result;
 
1153
  return ThrowReferenceError(String::cast(args[0]));
 
1154
}
 
1155
 
 
1156
 
 
1157
RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
 
1158
  PropertyAttributes attr;
 
1159
  MaybeObject* result = LoadWithInterceptor(&args, &attr);
 
1160
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
 
1161
  // This is call IC. In this case, we simply return the undefined result which
 
1162
  // will lead to an exception when trying to invoke the result as a
 
1163
  // function.
 
1164
  return result;
 
1165
}
 
1166
 
 
1167
 
 
1168
RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
 
1169
  ASSERT(args.length() == 4);
 
1170
  JSObject* recv = JSObject::cast(args[0]);
 
1171
  String* name = String::cast(args[1]);
 
1172
  Object* value = args[2];
 
1173
  ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
 
1174
  StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
 
1175
  ASSERT(recv->HasNamedInterceptor());
 
1176
  PropertyAttributes attr = NONE;
 
1177
  MaybeObject* result = recv->SetPropertyWithInterceptor(
 
1178
      name, value, attr, strict_mode);
 
1179
  return result;
 
1180
}
 
1181
 
 
1182
 
 
1183
RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
 
1184
  JSObject* receiver = JSObject::cast(args[0]);
 
1185
  ASSERT(args.smi_at(1) >= 0);
 
1186
  uint32_t index = args.smi_at(1);
 
1187
  return receiver->GetElementWithInterceptor(receiver, index);
 
1188
}
 
1189
 
 
1190
 
 
1191
Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
 
1192
  int argc = Code::ExtractArgumentsCountFromFlags(flags);
 
1193
  Code::Kind kind = Code::ExtractKindFromFlags(flags);
 
1194
  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
 
1195
  if (kind == Code::CALL_IC) {
 
1196
    CallIC::GenerateInitialize(masm(), argc, extra_state);
 
1197
  } else {
 
1198
    KeyedCallIC::GenerateInitialize(masm(), argc);
 
1199
  }
 
1200
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
 
1201
  isolate()->counters()->call_initialize_stubs()->Increment();
 
1202
  PROFILE(isolate(),
 
1203
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
 
1204
                          *code, code->arguments_count()));
 
1205
  GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
 
1206
  return code;
 
1207
}
 
1208
 
 
1209
 
 
1210
Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
 
1211
  int argc = Code::ExtractArgumentsCountFromFlags(flags);
 
1212
  // The code of the PreMonomorphic stub is the same as the code
 
1213
  // of the Initialized stub.  They just differ on the code object flags.
 
1214
  Code::Kind kind = Code::ExtractKindFromFlags(flags);
 
1215
  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
 
1216
  if (kind == Code::CALL_IC) {
 
1217
    CallIC::GenerateInitialize(masm(), argc, extra_state);
 
1218
  } else {
 
1219
    KeyedCallIC::GenerateInitialize(masm(), argc);
 
1220
  }
 
1221
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
 
1222
  isolate()->counters()->call_premonomorphic_stubs()->Increment();
 
1223
  PROFILE(isolate(),
 
1224
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
 
1225
                          *code, code->arguments_count()));
 
1226
  GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
 
1227
  return code;
 
1228
}
 
1229
 
 
1230
 
 
1231
Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
 
1232
  int argc = Code::ExtractArgumentsCountFromFlags(flags);
 
1233
  Code::Kind kind = Code::ExtractKindFromFlags(flags);
 
1234
  if (kind == Code::CALL_IC) {
 
1235
    // Call normal is always with a explict receiver.
 
1236
    ASSERT(!CallIC::Contextual::decode(
 
1237
        Code::ExtractExtraICStateFromFlags(flags)));
 
1238
    CallIC::GenerateNormal(masm(), argc);
 
1239
  } else {
 
1240
    KeyedCallIC::GenerateNormal(masm(), argc);
 
1241
  }
 
1242
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
 
1243
  isolate()->counters()->call_normal_stubs()->Increment();
 
1244
  PROFILE(isolate(),
 
1245
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
 
1246
                          *code, code->arguments_count()));
 
1247
  GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
 
1248
  return code;
 
1249
}
 
1250
 
 
1251
 
 
1252
Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
 
1253
  int argc = Code::ExtractArgumentsCountFromFlags(flags);
 
1254
  Code::Kind kind = Code::ExtractKindFromFlags(flags);
 
1255
  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
 
1256
  if (kind == Code::CALL_IC) {
 
1257
    CallIC::GenerateMegamorphic(masm(), argc, extra_state);
 
1258
  } else {
 
1259
    KeyedCallIC::GenerateMegamorphic(masm(), argc);
 
1260
  }
 
1261
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
 
1262
  isolate()->counters()->call_megamorphic_stubs()->Increment();
 
1263
  PROFILE(isolate(),
 
1264
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
 
1265
                          *code, code->arguments_count()));
 
1266
  GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
 
1267
  return code;
 
1268
}
 
1269
 
 
1270
 
 
1271
Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
 
1272
  int argc = Code::ExtractArgumentsCountFromFlags(flags);
 
1273
  KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
 
1274
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
 
1275
  PROFILE(isolate(),
 
1276
          CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
 
1277
                                          CALL_MEGAMORPHIC_TAG),
 
1278
                          *code, code->arguments_count()));
 
1279
  GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
 
1280
  return code;
 
1281
}
 
1282
 
 
1283
 
 
1284
Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
 
1285
  int argc = Code::ExtractArgumentsCountFromFlags(flags);
 
1286
  Code::Kind kind = Code::ExtractKindFromFlags(flags);
 
1287
  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
 
1288
  if (kind == Code::CALL_IC) {
 
1289
    CallIC::GenerateMiss(masm(), argc, extra_state);
 
1290
  } else {
 
1291
    KeyedCallIC::GenerateMiss(masm(), argc);
 
1292
  }
 
1293
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
 
1294
  isolate()->counters()->call_megamorphic_stubs()->Increment();
 
1295
  PROFILE(isolate(),
 
1296
          CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
 
1297
                          *code, code->arguments_count()));
 
1298
  GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
 
1299
  return code;
 
1300
}
 
1301
 
 
1302
 
 
1303
#ifdef ENABLE_DEBUGGER_SUPPORT
 
1304
Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
 
1305
  Debug::GenerateCallICDebugBreak(masm());
 
1306
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
 
1307
  PROFILE(isolate(),
 
1308
          CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
 
1309
                                          CALL_DEBUG_BREAK_TAG),
 
1310
                          *code, code->arguments_count()));
 
1311
  return code;
 
1312
}
 
1313
 
 
1314
 
 
1315
Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
 
1316
  // Use the same code for the the step in preparations as we do for the
 
1317
  // miss case.
 
1318
  int argc = Code::ExtractArgumentsCountFromFlags(flags);
 
1319
  Code::Kind kind = Code::ExtractKindFromFlags(flags);
 
1320
  if (kind == Code::CALL_IC) {
 
1321
    // For the debugger extra ic state is irrelevant.
 
1322
    CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
 
1323
  } else {
 
1324
    KeyedCallIC::GenerateMiss(masm(), argc);
 
1325
  }
 
1326
  Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
 
1327
  PROFILE(isolate(),
 
1328
          CodeCreateEvent(
 
1329
              CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
 
1330
              *code,
 
1331
              code->arguments_count()));
 
1332
  return code;
 
1333
}
 
1334
#endif  // ENABLE_DEBUGGER_SUPPORT
 
1335
 
 
1336
#undef CALL_LOGGER_TAG
 
1337
 
 
1338
 
 
1339
Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
 
1340
                                            const char* name) {
 
1341
  // Create code object in the heap.
 
1342
  CodeDesc desc;
 
1343
  masm_.GetCode(&desc);
 
1344
  Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
 
1345
#ifdef ENABLE_DISASSEMBLER
 
1346
  if (FLAG_print_code_stubs) code->Disassemble(name);
 
1347
#endif
 
1348
  return code;
 
1349
}
 
1350
 
 
1351
 
 
1352
Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
 
1353
                                            Handle<String> name) {
 
1354
  return (FLAG_print_code_stubs && !name.is_null())
 
1355
      ? GetCodeWithFlags(flags, *name->ToCString())
 
1356
      : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
 
1357
}
 
1358
 
 
1359
 
 
1360
void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
 
1361
                                         Handle<String> name,
 
1362
                                         LookupResult* lookup) {
 
1363
  holder->LocalLookupRealNamedProperty(*name, lookup);
 
1364
  if (lookup->IsFound()) return;
 
1365
  if (holder->GetPrototype()->IsNull()) return;
 
1366
  holder->GetPrototype()->Lookup(*name, lookup);
 
1367
}
 
1368
 
 
1369
 
 
1370
Handle<Code> LoadStubCompiler::GetCode(Code::StubType type,
 
1371
                                       Handle<String> name) {
 
1372
  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
 
1373
  Handle<Code> code = GetCodeWithFlags(flags, name);
 
1374
  PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
 
1375
  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
 
1376
  return code;
 
1377
}
 
1378
 
 
1379
 
 
1380
Handle<Code> KeyedLoadStubCompiler::GetCode(Code::StubType type,
 
1381
                                            Handle<String> name,
 
1382
                                            InlineCacheState state) {
 
1383
  Code::Flags flags = Code::ComputeFlags(
 
1384
      Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
 
1385
  Handle<Code> code = GetCodeWithFlags(flags, name);
 
1386
  PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
 
1387
  GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
 
1388
  return code;
 
1389
}
 
1390
 
 
1391
 
 
1392
Handle<Code> StoreStubCompiler::GetCode(Code::StubType type,
 
1393
                                        Handle<String> name) {
 
1394
  Code::Flags flags =
 
1395
      Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
 
1396
  Handle<Code> code = GetCodeWithFlags(flags, name);
 
1397
  PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
 
1398
  GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
 
1399
  return code;
 
1400
}
 
1401
 
 
1402
 
 
1403
Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type,
 
1404
                                             Handle<String> name,
 
1405
                                             InlineCacheState state) {
 
1406
  Code::ExtraICState extra_state =
 
1407
      Code::ComputeExtraICState(grow_mode_, strict_mode_);
 
1408
  Code::Flags flags =
 
1409
      Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type);
 
1410
  Handle<Code> code = GetCodeWithFlags(flags, name);
 
1411
  PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
 
1412
  GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
 
1413
  return code;
 
1414
}
 
1415
 
 
1416
 
 
1417
void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
 
1418
    MacroAssembler* masm) {
 
1419
  KeyedStoreIC::GenerateSlow(masm);
 
1420
}
 
1421
 
 
1422
 
 
1423
CallStubCompiler::CallStubCompiler(Isolate* isolate,
 
1424
                                   int argc,
 
1425
                                   Code::Kind kind,
 
1426
                                   Code::ExtraICState extra_state,
 
1427
                                   InlineCacheHolderFlag cache_holder)
 
1428
    : StubCompiler(isolate),
 
1429
      arguments_(argc),
 
1430
      kind_(kind),
 
1431
      extra_state_(extra_state),
 
1432
      cache_holder_(cache_holder) {
 
1433
}
 
1434
 
 
1435
 
 
1436
bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
 
1437
  if (function->shared()->HasBuiltinFunctionId()) {
 
1438
    BuiltinFunctionId id = function->shared()->builtin_function_id();
 
1439
#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
 
1440
    CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
 
1441
#undef CALL_GENERATOR_CASE
 
1442
  }
 
1443
 
 
1444
  CallOptimization optimization(function);
 
1445
  return optimization.is_simple_api_call();
 
1446
}
 
1447
 
 
1448
 
 
1449
Handle<Code> CallStubCompiler::CompileCustomCall(
 
1450
    Handle<Object> object,
 
1451
    Handle<JSObject> holder,
 
1452
    Handle<JSGlobalPropertyCell> cell,
 
1453
    Handle<JSFunction> function,
 
1454
    Handle<String> fname) {
 
1455
  ASSERT(HasCustomCallGenerator(function));
 
1456
 
 
1457
  if (function->shared()->HasBuiltinFunctionId()) {
 
1458
    BuiltinFunctionId id = function->shared()->builtin_function_id();
 
1459
#define CALL_GENERATOR_CASE(name)                               \
 
1460
    if (id == k##name) {                                        \
 
1461
      return CallStubCompiler::Compile##name##Call(object,      \
 
1462
                                                   holder,      \
 
1463
                                                   cell,        \
 
1464
                                                   function,    \
 
1465
                                                   fname);      \
 
1466
    }
 
1467
    CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
 
1468
#undef CALL_GENERATOR_CASE
 
1469
  }
 
1470
  CallOptimization optimization(function);
 
1471
  ASSERT(optimization.is_simple_api_call());
 
1472
  return CompileFastApiCall(optimization,
 
1473
                            object,
 
1474
                            holder,
 
1475
                            cell,
 
1476
                            function,
 
1477
                            fname);
 
1478
}
 
1479
 
 
1480
 
 
1481
Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
 
1482
                                       Handle<String> name) {
 
1483
  int argc = arguments_.immediate();
 
1484
  Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
 
1485
                                                    type,
 
1486
                                                    extra_state_,
 
1487
                                                    cache_holder_,
 
1488
                                                    argc);
 
1489
  return GetCodeWithFlags(flags, name);
 
1490
}
 
1491
 
 
1492
 
 
1493
Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
 
1494
  Handle<String> function_name;
 
1495
  if (function->shared()->name()->IsString()) {
 
1496
    function_name = Handle<String>(String::cast(function->shared()->name()));
 
1497
  }
 
1498
  return GetCode(Code::CONSTANT_FUNCTION, function_name);
 
1499
}
 
1500
 
 
1501
 
 
1502
Handle<Code> ConstructStubCompiler::GetCode() {
 
1503
  Code::Flags flags = Code::ComputeFlags(Code::STUB);
 
1504
  Handle<Code> code = GetCodeWithFlags(flags, "ConstructStub");
 
1505
  PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, "ConstructStub"));
 
1506
  GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", *code));
 
1507
  return code;
 
1508
}
 
1509
 
 
1510
 
 
1511
CallOptimization::CallOptimization(LookupResult* lookup) {
 
1512
  if (lookup->IsFound() &&
 
1513
      lookup->IsCacheable() &&
 
1514
      lookup->type() == CONSTANT_FUNCTION) {
 
1515
    // We only optimize constant function calls.
 
1516
    Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
 
1517
  } else {
 
1518
    Initialize(Handle<JSFunction>::null());
 
1519
  }
 
1520
}
 
1521
 
 
1522
CallOptimization::CallOptimization(Handle<JSFunction> function) {
 
1523
  Initialize(function);
 
1524
}
 
1525
 
 
1526
 
 
1527
int CallOptimization::GetPrototypeDepthOfExpectedType(
 
1528
    Handle<JSObject> object,
 
1529
    Handle<JSObject> holder) const {
 
1530
  ASSERT(is_simple_api_call());
 
1531
  if (expected_receiver_type_.is_null()) return 0;
 
1532
  int depth = 0;
 
1533
  while (!object.is_identical_to(holder)) {
 
1534
    if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
 
1535
    object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
 
1536
    ++depth;
 
1537
  }
 
1538
  if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
 
1539
  return kInvalidProtoDepth;
 
1540
}
 
1541
 
 
1542
 
 
1543
void CallOptimization::Initialize(Handle<JSFunction> function) {
 
1544
  constant_function_ = Handle<JSFunction>::null();
 
1545
  is_simple_api_call_ = false;
 
1546
  expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
 
1547
  api_call_info_ = Handle<CallHandlerInfo>::null();
 
1548
 
 
1549
  if (function.is_null() || !function->is_compiled()) return;
 
1550
 
 
1551
  constant_function_ = function;
 
1552
  AnalyzePossibleApiFunction(function);
 
1553
}
 
1554
 
 
1555
 
 
1556
void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
 
1557
  if (!function->shared()->IsApiFunction()) return;
 
1558
  Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
 
1559
 
 
1560
  // Require a C++ callback.
 
1561
  if (info->call_code()->IsUndefined()) return;
 
1562
  api_call_info_ =
 
1563
      Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
 
1564
 
 
1565
  // Accept signatures that either have no restrictions at all or
 
1566
  // only have restrictions on the receiver.
 
1567
  if (!info->signature()->IsUndefined()) {
 
1568
    Handle<SignatureInfo> signature =
 
1569
        Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
 
1570
    if (!signature->args()->IsUndefined()) return;
 
1571
    if (!signature->receiver()->IsUndefined()) {
 
1572
      expected_receiver_type_ =
 
1573
          Handle<FunctionTemplateInfo>(
 
1574
              FunctionTemplateInfo::cast(signature->receiver()));
 
1575
    }
 
1576
  }
 
1577
 
 
1578
  is_simple_api_call_ = true;
 
1579
}
 
1580
 
 
1581
 
 
1582
} }  // namespace v8::internal