The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / code-stubs.cc @ f230a1cf

History | View | Annotate | Download (41.4 KB)

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 "bootstrapper.h"
31
#include "code-stubs.h"
32
#include "cpu-profiler.h"
33
#include "stub-cache.h"
34
#include "factory.h"
35
#include "gdb-jit.h"
36
#include "macro-assembler.h"
37

    
38
namespace v8 {
39
namespace internal {
40

    
41

    
42
CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
43
    : register_param_count_(-1),
44
      stack_parameter_count_(no_reg),
45
      hint_stack_parameter_count_(-1),
46
      function_mode_(NOT_JS_FUNCTION_STUB_MODE),
47
      register_params_(NULL),
48
      deoptimization_handler_(NULL),
49
      miss_handler_(),
50
      has_miss_handler_(false) { }
51

    
52

    
53
bool CodeStub::FindCodeInCache(Code** code_out, Isolate* isolate) {
54
  UnseededNumberDictionary* stubs = isolate->heap()->code_stubs();
55
  int index = stubs->FindEntry(GetKey());
56
  if (index != UnseededNumberDictionary::kNotFound) {
57
    *code_out = Code::cast(stubs->ValueAt(index));
58
    return true;
59
  }
60
  return false;
61
}
62

    
63

    
64
SmartArrayPointer<const char> CodeStub::GetName() {
65
  char buffer[100];
66
  NoAllocationStringAllocator allocator(buffer,
67
                                        static_cast<unsigned>(sizeof(buffer)));
68
  StringStream stream(&allocator);
69
  PrintName(&stream);
70
  return stream.ToCString();
71
}
72

    
73

    
74
void CodeStub::RecordCodeGeneration(Code* code, Isolate* isolate) {
75
  SmartArrayPointer<const char> name = GetName();
76
  PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, *name));
77
  GDBJIT(AddCode(GDBJITInterface::STUB, *name, code));
78
  Counters* counters = isolate->counters();
79
  counters->total_stubs_code_size()->Increment(code->instruction_size());
80
}
81

    
82

    
83
Code::Kind CodeStub::GetCodeKind() const {
84
  return Code::STUB;
85
}
86

    
87

    
88
Handle<Code> CodeStub::GetCodeCopyFromTemplate(Isolate* isolate) {
89
  Handle<Code> ic = GetCode(isolate);
90
  ic = isolate->factory()->CopyCode(ic);
91
  RecordCodeGeneration(*ic, isolate);
92
  return ic;
93
}
94

    
95

    
96
Handle<Code> PlatformCodeStub::GenerateCode(Isolate* isolate) {
97
  Factory* factory = isolate->factory();
98

    
99
  // Generate the new code.
100
  MacroAssembler masm(isolate, NULL, 256);
101

    
102
  {
103
    // Update the static counter each time a new code stub is generated.
104
    isolate->counters()->code_stubs()->Increment();
105

    
106
    // Nested stubs are not allowed for leaves.
107
    AllowStubCallsScope allow_scope(&masm, false);
108

    
109
    // Generate the code for the stub.
110
    masm.set_generating_stub(true);
111
    NoCurrentFrameScope scope(&masm);
112
    Generate(&masm);
113
  }
114

    
115
  // Create the code object.
116
  CodeDesc desc;
117
  masm.GetCode(&desc);
118

    
119
  // Copy the generated code into a heap object.
120
  Code::Flags flags = Code::ComputeFlags(
121
      GetCodeKind(),
122
      GetICState(),
123
      GetExtraICState(),
124
      GetStubType(),
125
      GetStubFlags());
126
  Handle<Code> new_object = factory->NewCode(
127
      desc, flags, masm.CodeObject(), NeedsImmovableCode());
128
  return new_object;
129
}
130

    
131

    
132
void CodeStub::VerifyPlatformFeatures(Isolate* isolate) {
133
  ASSERT(CpuFeatures::VerifyCrossCompiling());
134
}
135

    
136

    
137
Handle<Code> CodeStub::GetCode(Isolate* isolate) {
138
  Factory* factory = isolate->factory();
139
  Heap* heap = isolate->heap();
140
  Code* code;
141
  if (UseSpecialCache()
142
      ? FindCodeInSpecialCache(&code, isolate)
143
      : FindCodeInCache(&code, isolate)) {
144
    ASSERT(IsPregenerated(isolate) == code->is_pregenerated());
145
    ASSERT(GetCodeKind() == code->kind());
146
    return Handle<Code>(code);
147
  }
148

    
149
#ifdef DEBUG
150
  VerifyPlatformFeatures(isolate);
151
#endif
152

    
153
  {
154
    HandleScope scope(isolate);
155

    
156
    Handle<Code> new_object = GenerateCode(isolate);
157
    new_object->set_major_key(MajorKey());
158
    FinishCode(new_object);
159
    RecordCodeGeneration(*new_object, isolate);
160

    
161
#ifdef ENABLE_DISASSEMBLER
162
    if (FLAG_print_code_stubs) {
163
      new_object->Disassemble(*GetName());
164
      PrintF("\n");
165
    }
166
#endif
167

    
168
    if (UseSpecialCache()) {
169
      AddToSpecialCache(new_object);
170
    } else {
171
      // Update the dictionary and the root in Heap.
172
      Handle<UnseededNumberDictionary> dict =
173
          factory->DictionaryAtNumberPut(
174
              Handle<UnseededNumberDictionary>(heap->code_stubs()),
175
              GetKey(),
176
              new_object);
177
      heap->public_set_code_stubs(*dict);
178
    }
179
    code = *new_object;
180
  }
181

    
182
  Activate(code);
183
  ASSERT(!NeedsImmovableCode() ||
184
         heap->lo_space()->Contains(code) ||
185
         heap->code_space()->FirstPage()->Contains(code->address()));
186
  return Handle<Code>(code, isolate);
187
}
188

    
189

    
190
const char* CodeStub::MajorName(CodeStub::Major major_key,
191
                                bool allow_unknown_keys) {
192
  switch (major_key) {
193
#define DEF_CASE(name) case name: return #name "Stub";
194
    CODE_STUB_LIST(DEF_CASE)
195
#undef DEF_CASE
196
    default:
197
      if (!allow_unknown_keys) {
198
        UNREACHABLE();
199
      }
200
      return NULL;
201
  }
202
}
203

    
204

    
205
void CodeStub::PrintBaseName(StringStream* stream) {
206
  stream->Add("%s", MajorName(MajorKey(), false));
207
}
208

    
209

    
210
void CodeStub::PrintName(StringStream* stream) {
211
  PrintBaseName(stream);
212
  PrintState(stream);
213
}
214

    
215

    
216
void BinaryOpStub::PrintBaseName(StringStream* stream) {
217
  const char* op_name = Token::Name(op_);
218
  const char* ovr = "";
219
  if (mode_ == OVERWRITE_LEFT) ovr = "_ReuseLeft";
220
  if (mode_ == OVERWRITE_RIGHT) ovr = "_ReuseRight";
221
  stream->Add("BinaryOpStub_%s%s", op_name, ovr);
222
}
223

    
224

    
225
void BinaryOpStub::PrintState(StringStream* stream) {
226
  stream->Add("(");
227
  stream->Add(StateToName(left_state_));
228
  stream->Add("*");
229
  if (fixed_right_arg_.has_value) {
230
    stream->Add("%d", fixed_right_arg_.value);
231
  } else {
232
    stream->Add(StateToName(right_state_));
233
  }
234
  stream->Add("->");
235
  stream->Add(StateToName(result_state_));
236
  stream->Add(")");
237
}
238

    
239

    
240
Maybe<Handle<Object> > BinaryOpStub::Result(Handle<Object> left,
241
                                            Handle<Object> right,
242
                                            Isolate* isolate) {
243
  Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
244
  Builtins::JavaScript func = BinaryOpIC::TokenToJSBuiltin(op_);
245
  Object* builtin = builtins->javascript_builtin(func);
246
  Handle<JSFunction> builtin_function =
247
      Handle<JSFunction>(JSFunction::cast(builtin), isolate);
248
  bool caught_exception;
249
  Handle<Object> result = Execution::Call(isolate, builtin_function, left,
250
      1, &right, &caught_exception);
251
  return Maybe<Handle<Object> >(!caught_exception, result);
252
}
253

    
254

    
255
void BinaryOpStub::Initialize() {
256
  fixed_right_arg_.has_value = false;
257
  left_state_ = right_state_ = result_state_ = NONE;
258
}
259

    
260

    
261
void BinaryOpStub::Generate(Token::Value op,
262
                            State left,
263
                            State right,
264
                            State result,
265
                            OverwriteMode mode,
266
                            Isolate* isolate) {
267
  BinaryOpStub stub(INITIALIZED);
268
  stub.op_ = op;
269
  stub.left_state_ = left;
270
  stub.right_state_ = right;
271
  stub.result_state_ = result;
272
  stub.mode_ = mode;
273
  stub.GetCode(isolate);
274
}
275

    
276

    
277
void BinaryOpStub::Generate(Token::Value op,
278
                            State left,
279
                            int right,
280
                            State result,
281
                            OverwriteMode mode,
282
                            Isolate* isolate) {
283
  BinaryOpStub stub(INITIALIZED);
284
  stub.op_ = op;
285
  stub.left_state_ = left;
286
  stub.fixed_right_arg_.has_value = true;
287
  stub.fixed_right_arg_.value = right;
288
  stub.right_state_ = SMI;
289
  stub.result_state_ = result;
290
  stub.mode_ = mode;
291
  stub.GetCode(isolate);
292
}
293

    
294

    
295
void BinaryOpStub::GenerateAheadOfTime(Isolate* isolate) {
296
  Token::Value binop[] = {Token::SUB, Token::MOD, Token::DIV, Token::MUL,
297
                          Token::ADD, Token::SAR, Token::BIT_OR, Token::BIT_AND,
298
                          Token::BIT_XOR, Token::SHL, Token::SHR};
299
  for (unsigned i = 0; i < ARRAY_SIZE(binop); i++) {
300
    BinaryOpStub stub(UNINITIALIZED);
301
    stub.op_ = binop[i];
302
    stub.GetCode(isolate);
303
  }
304

    
305
  // TODO(olivf) We should investigate why adding stubs to the snapshot is so
306
  // expensive at runtime. When solved we should be able to add most binops to
307
  // the snapshot instead of hand-picking them.
308
  // Generated list of commonly used stubs
309
  Generate(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE, isolate);
310
  Generate(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
311
  Generate(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
312
  Generate(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT, isolate);
313
  Generate(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
314
  Generate(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
315
  Generate(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
316
  Generate(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE, isolate);
317
  Generate(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
318
  Generate(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
319
  Generate(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
320
  Generate(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
321
  Generate(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT, isolate);
322
  Generate(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
323
  Generate(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
324
  Generate(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
325
  Generate(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
326
  Generate(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
327
  Generate(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
328
  Generate(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE, isolate);
329
  Generate(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
330
  Generate(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
331
  Generate(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
332
  Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
333
  Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
334
  Generate(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT, isolate);
335
  Generate(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
336
  Generate(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE, isolate);
337
  Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
338
  Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
339
  Generate(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE, isolate);
340
  Generate(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT, isolate);
341
  Generate(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE, isolate);
342
  Generate(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
343
  Generate(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE, isolate);
344
  Generate(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT, isolate);
345
  Generate(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
346
  Generate(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT, isolate);
347
  Generate(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
348
  Generate(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
349
  Generate(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE, isolate);
350
  Generate(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT, isolate);
351
  Generate(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT, isolate);
352
  Generate(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE, isolate);
353
  Generate(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
354
  Generate(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
355
  Generate(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
356
  Generate(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
357
  Generate(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT, isolate);
358
  Generate(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE, isolate);
359
  Generate(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
360
  Generate(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
361
  Generate(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
362
  Generate(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
363
  Generate(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE, isolate);
364
  Generate(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT, isolate);
365
  Generate(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT, isolate);
366
  Generate(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
367
  Generate(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT, isolate);
368
  Generate(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
369
  Generate(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT, isolate);
370
  Generate(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT, isolate);
371
  Generate(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
372
  Generate(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
373
  Generate(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE, isolate);
374
  Generate(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
375
  Generate(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
376
  Generate(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE, isolate);
377
  Generate(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT, isolate);
378
  Generate(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE, isolate);
379
  Generate(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE, isolate);
380
  Generate(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
381
  Generate(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
382
  Generate(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE, isolate);
383
  Generate(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE, isolate);
384
  Generate(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
385
  Generate(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE, isolate);
386
  Generate(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
387
  Generate(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT, isolate);
388
  Generate(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE, isolate);
389
  Generate(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
390
  Generate(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
391
  Generate(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE, isolate);
392
  Generate(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
393
  Generate(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
394
  Generate(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
395
  Generate(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE, isolate);
396
  Generate(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE, isolate);
397
  Generate(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
398
  Generate(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
399
  Generate(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
400
  Generate(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
401
  Generate(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
402
  Generate(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
403
  Generate(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
404
  Generate(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE, isolate);
405
  Generate(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
406
  Generate(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT, isolate);
407
  Generate(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
408
  Generate(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
409
  Generate(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
410
  Generate(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE, isolate);
411
  Generate(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT, isolate);
412
  Generate(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
413
  Generate(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE, isolate);
414
  Generate(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
415
  Generate(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
416
  Generate(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
417
  Generate(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT, isolate);
418
  Generate(Token::MOD, SMI, 2, SMI, NO_OVERWRITE, isolate);
419
  Generate(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE, isolate);
420
  Generate(Token::MOD, SMI, 32, SMI, NO_OVERWRITE, isolate);
421
  Generate(Token::MOD, SMI, 4, SMI, NO_OVERWRITE, isolate);
422
  Generate(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT, isolate);
423
  Generate(Token::MOD, SMI, 8, SMI, NO_OVERWRITE, isolate);
424
  Generate(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE, isolate);
425
  Generate(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
426
  Generate(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE, isolate);
427
  Generate(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
428
  Generate(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
429
  Generate(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
430
  Generate(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE, isolate);
431
  Generate(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
432
  Generate(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE, isolate);
433
  Generate(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
434
  Generate(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
435
  Generate(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT, isolate);
436
  Generate(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
437
  Generate(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
438
  Generate(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
439
  Generate(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
440
  Generate(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
441
  Generate(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE, isolate);
442
  Generate(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT, isolate);
443
  Generate(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE, isolate);
444
  Generate(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
445
  Generate(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
446
  Generate(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
447
  Generate(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE, isolate);
448
  Generate(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE, isolate);
449
  Generate(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT, isolate);
450
  Generate(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE, isolate);
451
  Generate(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
452
  Generate(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
453
  Generate(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
454
  Generate(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
455
  Generate(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
456
  Generate(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
457
  Generate(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
458
  Generate(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
459
  Generate(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
460
  Generate(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE, isolate);
461
  Generate(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
462
  Generate(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE, isolate);
463
  Generate(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
464
  Generate(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT, isolate);
465
  Generate(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE, isolate);
466
  Generate(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT, isolate);
467
  Generate(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT, isolate);
468
  Generate(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE, isolate);
469
  Generate(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
470
  Generate(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
471
  Generate(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE, isolate);
472
  Generate(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT, isolate);
473
  Generate(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT, isolate);
474
  Generate(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE, isolate);
475
  Generate(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT, isolate);
476
  Generate(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT, isolate);
477
  Generate(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE, isolate);
478
  Generate(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
479
  Generate(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
480
  Generate(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE, isolate);
481
  Generate(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
482
  Generate(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE, isolate);
483
  Generate(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
484
  Generate(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT, isolate);
485
  Generate(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT, isolate);
486
  Generate(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE, isolate);
487
  Generate(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT, isolate);
488
  Generate(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE, isolate);
489
  Generate(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
490
  Generate(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
491
  Generate(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE, isolate);
492
  Generate(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT, isolate);
493
  Generate(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT, isolate);
494
  Generate(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE, isolate);
495
  Generate(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE, isolate);
496
  Generate(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT, isolate);
497
  Generate(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
498
  Generate(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE, isolate);
499
  Generate(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT, isolate);
500
  Generate(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
501
}
502

    
503

    
504
bool BinaryOpStub::can_encode_arg_value(int32_t value) const {
505
  return op_ == Token::MOD && value > 0 && IsPowerOf2(value) &&
506
         FixedRightArgValueBits::is_valid(WhichPowerOf2(value));
507
}
508

    
509

    
510
int BinaryOpStub::encode_arg_value(int32_t value) const {
511
  ASSERT(can_encode_arg_value(value));
512
  return WhichPowerOf2(value);
513
}
514

    
515

    
516
int32_t BinaryOpStub::decode_arg_value(int value)  const {
517
  return 1 << value;
518
}
519

    
520

    
521
int BinaryOpStub::encode_token(Token::Value op) const {
522
  ASSERT(op >= FIRST_TOKEN && op <= LAST_TOKEN);
523
  return op - FIRST_TOKEN;
524
}
525

    
526

    
527
Token::Value BinaryOpStub::decode_token(int op) const {
528
  int res = op + FIRST_TOKEN;
529
  ASSERT(res >= FIRST_TOKEN && res <= LAST_TOKEN);
530
  return static_cast<Token::Value>(res);
531
}
532

    
533

    
534
const char* BinaryOpStub::StateToName(State state) {
535
  switch (state) {
536
    case NONE:
537
      return "None";
538
    case SMI:
539
      return "Smi";
540
    case INT32:
541
      return "Int32";
542
    case NUMBER:
543
      return "Number";
544
    case STRING:
545
      return "String";
546
    case GENERIC:
547
      return "Generic";
548
  }
549
  return "";
550
}
551

    
552

    
553
void BinaryOpStub::UpdateStatus(Handle<Object> left,
554
                                Handle<Object> right,
555
                                Maybe<Handle<Object> > result) {
556
  int old_state = GetExtraICState();
557

    
558
  UpdateStatus(left, &left_state_);
559
  UpdateStatus(right, &right_state_);
560

    
561
  int32_t value;
562
  bool new_has_fixed_right_arg =
563
      right->ToInt32(&value) && can_encode_arg_value(value) &&
564
      (left_state_ == SMI || left_state_ == INT32) &&
565
      (result_state_ == NONE || !fixed_right_arg_.has_value);
566

    
567
  fixed_right_arg_ = Maybe<int32_t>(new_has_fixed_right_arg, value);
568

    
569
  if (result.has_value) UpdateStatus(result.value, &result_state_);
570

    
571
  State max_input = Max(left_state_, right_state_);
572

    
573
  if (!has_int_result() && op_ != Token::SHR &&
574
      max_input <= NUMBER && max_input > result_state_) {
575
    result_state_ = max_input;
576
  }
577

    
578
  ASSERT(result_state_ <= (has_int_result() ? INT32 : NUMBER) ||
579
         op_ == Token::ADD);
580

    
581
  if (old_state == GetExtraICState()) {
582
    // Tagged operations can lead to non-truncating HChanges
583
    if (left->IsUndefined() || left->IsBoolean()) {
584
      left_state_ = GENERIC;
585
    } else if (right->IsUndefined() || right->IsBoolean()) {
586
      right_state_ = GENERIC;
587
    } else {
588
      // Since the fpu is to precise, we might bail out on numbers which
589
      // actually would truncate with 64 bit precision.
590
      ASSERT(!CpuFeatures::IsSupported(SSE2) &&
591
             result_state_ <= INT32);
592
      result_state_ = NUMBER;
593
    }
594
  }
595
}
596

    
597

    
598
void BinaryOpStub::UpdateStatus(Handle<Object> object,
599
                                State* state) {
600
  bool is_truncating = (op_ == Token::BIT_AND || op_ == Token::BIT_OR ||
601
                        op_ == Token::BIT_XOR || op_ == Token::SAR ||
602
                        op_ == Token::SHL || op_ == Token::SHR);
603
  v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(object);
604
  if (object->IsBoolean() && is_truncating) {
605
    // Booleans are converted by truncating by HChange.
606
    type = TypeInfo::Integer32();
607
  }
608
  if (object->IsUndefined()) {
609
    // Undefined will be automatically truncated for us by HChange.
610
    type = is_truncating ? TypeInfo::Integer32() : TypeInfo::Double();
611
  }
612
  State int_state = SmiValuesAre32Bits() ? NUMBER : INT32;
613
  State new_state = NONE;
614
  if (type.IsSmi()) {
615
    new_state = SMI;
616
  } else if (type.IsInteger32()) {
617
    new_state = int_state;
618
  } else if (type.IsNumber()) {
619
    new_state = NUMBER;
620
  } else if (object->IsString() && operation() == Token::ADD) {
621
    new_state = STRING;
622
  } else {
623
    new_state = GENERIC;
624
  }
625
  if ((new_state <= NUMBER && *state >  NUMBER) ||
626
      (new_state >  NUMBER && *state <= NUMBER && *state != NONE)) {
627
    new_state = GENERIC;
628
  }
629
  *state = Max(*state, new_state);
630
}
631

    
632

    
633
Handle<Type> BinaryOpStub::StateToType(State state,
634
                                       Isolate* isolate) {
635
  Handle<Type> t = handle(Type::None(), isolate);
636
  switch (state) {
637
    case NUMBER:
638
      t = handle(Type::Union(t, handle(Type::Double(), isolate)), isolate);
639
      // Fall through.
640
    case INT32:
641
      t = handle(Type::Union(t, handle(Type::Signed32(), isolate)), isolate);
642
      // Fall through.
643
    case SMI:
644
      t = handle(Type::Union(t, handle(Type::Smi(), isolate)), isolate);
645
      break;
646

    
647
    case STRING:
648
      t = handle(Type::Union(t, handle(Type::String(), isolate)), isolate);
649
      break;
650
    case GENERIC:
651
      return handle(Type::Any(), isolate);
652
      break;
653
    case NONE:
654
      break;
655
  }
656
  return t;
657
}
658

    
659

    
660
Handle<Type> BinaryOpStub::GetLeftType(Isolate* isolate) const {
661
  return StateToType(left_state_, isolate);
662
}
663

    
664

    
665
Handle<Type> BinaryOpStub::GetRightType(Isolate* isolate) const {
666
  return StateToType(right_state_, isolate);
667
}
668

    
669

    
670
Handle<Type> BinaryOpStub::GetResultType(Isolate* isolate) const {
671
  if (HasSideEffects(isolate)) return StateToType(NONE, isolate);
672
  if (result_state_ == GENERIC && op_ == Token::ADD) {
673
    return handle(Type::Union(handle(Type::Number(), isolate),
674
                              handle(Type::String(), isolate)), isolate);
675
  }
676
  ASSERT(result_state_ != GENERIC);
677
  if (result_state_ == NUMBER && op_ == Token::SHR) {
678
    return handle(Type::Unsigned32(), isolate);
679
  }
680
  return StateToType(result_state_, isolate);
681
}
682

    
683

    
684
InlineCacheState ICCompareStub::GetICState() {
685
  CompareIC::State state = Max(left_, right_);
686
  switch (state) {
687
    case CompareIC::UNINITIALIZED:
688
      return ::v8::internal::UNINITIALIZED;
689
    case CompareIC::SMI:
690
    case CompareIC::NUMBER:
691
    case CompareIC::INTERNALIZED_STRING:
692
    case CompareIC::STRING:
693
    case CompareIC::UNIQUE_NAME:
694
    case CompareIC::OBJECT:
695
    case CompareIC::KNOWN_OBJECT:
696
      return MONOMORPHIC;
697
    case CompareIC::GENERIC:
698
      return ::v8::internal::GENERIC;
699
  }
700
  UNREACHABLE();
701
  return ::v8::internal::UNINITIALIZED;
702
}
703

    
704

    
705
void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
706
  ASSERT(*known_map_ != NULL);
707
  Isolate* isolate = new_object->GetIsolate();
708
  Factory* factory = isolate->factory();
709
  return Map::UpdateCodeCache(known_map_,
710
                              strict() ?
711
                                  factory->strict_compare_ic_string() :
712
                                  factory->compare_ic_string(),
713
                              new_object);
714
}
715

    
716

    
717
bool ICCompareStub::FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
718
  Factory* factory = isolate->factory();
719
  Code::Flags flags = Code::ComputeFlags(
720
      GetCodeKind(),
721
      UNINITIALIZED);
722
  ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
723
  Handle<Object> probe(
724
      known_map_->FindInCodeCache(
725
        strict() ?
726
            *factory->strict_compare_ic_string() :
727
            *factory->compare_ic_string(),
728
        flags),
729
      isolate);
730
  if (probe->IsCode()) {
731
    *code_out = Code::cast(*probe);
732
#ifdef DEBUG
733
    Token::Value cached_op;
734
    ICCompareStub::DecodeMinorKey((*code_out)->stub_info(), NULL, NULL, NULL,
735
                                  &cached_op);
736
    ASSERT(op_ == cached_op);
737
#endif
738
    return true;
739
  }
740
  return false;
741
}
742

    
743

    
744
int ICCompareStub::MinorKey() {
745
  return OpField::encode(op_ - Token::EQ) |
746
         LeftStateField::encode(left_) |
747
         RightStateField::encode(right_) |
748
         HandlerStateField::encode(state_);
749
}
750

    
751

    
752
void ICCompareStub::DecodeMinorKey(int minor_key,
753
                                   CompareIC::State* left_state,
754
                                   CompareIC::State* right_state,
755
                                   CompareIC::State* handler_state,
756
                                   Token::Value* op) {
757
  if (left_state) {
758
    *left_state =
759
        static_cast<CompareIC::State>(LeftStateField::decode(minor_key));
760
  }
761
  if (right_state) {
762
    *right_state =
763
        static_cast<CompareIC::State>(RightStateField::decode(minor_key));
764
  }
765
  if (handler_state) {
766
    *handler_state =
767
        static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
768
  }
769
  if (op) {
770
    *op = static_cast<Token::Value>(OpField::decode(minor_key) + Token::EQ);
771
  }
772
}
773

    
774

    
775
void ICCompareStub::Generate(MacroAssembler* masm) {
776
  switch (state_) {
777
    case CompareIC::UNINITIALIZED:
778
      GenerateMiss(masm);
779
      break;
780
    case CompareIC::SMI:
781
      GenerateSmis(masm);
782
      break;
783
    case CompareIC::NUMBER:
784
      GenerateNumbers(masm);
785
      break;
786
    case CompareIC::STRING:
787
      GenerateStrings(masm);
788
      break;
789
    case CompareIC::INTERNALIZED_STRING:
790
      GenerateInternalizedStrings(masm);
791
      break;
792
    case CompareIC::UNIQUE_NAME:
793
      GenerateUniqueNames(masm);
794
      break;
795
    case CompareIC::OBJECT:
796
      GenerateObjects(masm);
797
      break;
798
    case CompareIC::KNOWN_OBJECT:
799
      ASSERT(*known_map_ != NULL);
800
      GenerateKnownObjects(masm);
801
      break;
802
    case CompareIC::GENERIC:
803
      GenerateGeneric(masm);
804
      break;
805
  }
806
}
807

    
808

    
809
void CompareNilICStub::UpdateStatus(Handle<Object> object) {
810
  ASSERT(!state_.Contains(GENERIC));
811
  State old_state(state_);
812
  if (object->IsNull()) {
813
    state_.Add(NULL_TYPE);
814
  } else if (object->IsUndefined()) {
815
    state_.Add(UNDEFINED);
816
  } else if (object->IsUndetectableObject() ||
817
             object->IsOddball() ||
818
             !object->IsHeapObject()) {
819
    state_.RemoveAll();
820
    state_.Add(GENERIC);
821
  } else if (IsMonomorphic()) {
822
    state_.RemoveAll();
823
    state_.Add(GENERIC);
824
  } else {
825
    state_.Add(MONOMORPHIC_MAP);
826
  }
827
  TraceTransition(old_state, state_);
828
}
829

    
830

    
831
template<class StateType>
832
void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
833
  // Note: Although a no-op transition is semantically OK, it is hinting at a
834
  // bug somewhere in our state transition machinery.
835
  ASSERT(from != to);
836
  #ifdef DEBUG
837
  if (!FLAG_trace_ic) return;
838
  char buffer[100];
839
  NoAllocationStringAllocator allocator(buffer,
840
                                        static_cast<unsigned>(sizeof(buffer)));
841
  StringStream stream(&allocator);
842
  stream.Add("[");
843
  PrintBaseName(&stream);
844
  stream.Add(": ");
845
  from.Print(&stream);
846
  stream.Add("=>");
847
  to.Print(&stream);
848
  stream.Add("]\n");
849
  stream.OutputToStdOut();
850
  #endif
851
}
852

    
853

    
854
void CompareNilICStub::PrintBaseName(StringStream* stream) {
855
  CodeStub::PrintBaseName(stream);
856
  stream->Add((nil_value_ == kNullValue) ? "(NullValue)":
857
                                           "(UndefinedValue)");
858
}
859

    
860

    
861
void CompareNilICStub::PrintState(StringStream* stream) {
862
  state_.Print(stream);
863
}
864

    
865

    
866
void CompareNilICStub::State::Print(StringStream* stream) const {
867
  stream->Add("(");
868
  SimpleListPrinter printer(stream);
869
  if (IsEmpty()) printer.Add("None");
870
  if (Contains(UNDEFINED)) printer.Add("Undefined");
871
  if (Contains(NULL_TYPE)) printer.Add("Null");
872
  if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
873
  if (Contains(GENERIC)) printer.Add("Generic");
874
  stream->Add(")");
875
}
876

    
877

    
878
Handle<Type> CompareNilICStub::GetType(
879
    Isolate* isolate,
880
    Handle<Map> map) {
881
  if (state_.Contains(CompareNilICStub::GENERIC)) {
882
    return handle(Type::Any(), isolate);
883
  }
884

    
885
  Handle<Type> result(Type::None(), isolate);
886
  if (state_.Contains(CompareNilICStub::UNDEFINED)) {
887
    result = handle(Type::Union(result, handle(Type::Undefined(), isolate)),
888
                    isolate);
889
  }
890
  if (state_.Contains(CompareNilICStub::NULL_TYPE)) {
891
    result = handle(Type::Union(result, handle(Type::Null(), isolate)),
892
                    isolate);
893
  }
894
  if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
895
    Type* type = map.is_null() ? Type::Detectable() : Type::Class(map);
896
    result = handle(Type::Union(result, handle(type, isolate)), isolate);
897
  }
898

    
899
  return result;
900
}
901

    
902

    
903
Handle<Type> CompareNilICStub::GetInputType(
904
    Isolate* isolate,
905
    Handle<Map> map) {
906
  Handle<Type> output_type = GetType(isolate, map);
907
  Handle<Type> nil_type = handle(nil_value_ == kNullValue
908
      ? Type::Null() : Type::Undefined(), isolate);
909
  return handle(Type::Union(output_type, nil_type), isolate);
910
}
911

    
912

    
913
void InstanceofStub::PrintName(StringStream* stream) {
914
  const char* args = "";
915
  if (HasArgsInRegisters()) {
916
    args = "_REGS";
917
  }
918

    
919
  const char* inline_check = "";
920
  if (HasCallSiteInlineCheck()) {
921
    inline_check = "_INLINE";
922
  }
923

    
924
  const char* return_true_false_object = "";
925
  if (ReturnTrueFalseObject()) {
926
    return_true_false_object = "_TRUEFALSE";
927
  }
928

    
929
  stream->Add("InstanceofStub%s%s%s",
930
              args,
931
              inline_check,
932
              return_true_false_object);
933
}
934

    
935

    
936
void JSEntryStub::FinishCode(Handle<Code> code) {
937
  Handle<FixedArray> handler_table =
938
      code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
939
  handler_table->set(0, Smi::FromInt(handler_offset_));
940
  code->set_handler_table(*handler_table);
941
}
942

    
943

    
944
void KeyedLoadDictionaryElementStub::Generate(MacroAssembler* masm) {
945
  KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
946
}
947

    
948

    
949
void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
950
  CreateAllocationSiteStub stub;
951
  stub.GetCode(isolate)->set_is_pregenerated(true);
952
}
953

    
954

    
955
void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
956
  switch (elements_kind_) {
957
    case FAST_ELEMENTS:
958
    case FAST_HOLEY_ELEMENTS:
959
    case FAST_SMI_ELEMENTS:
960
    case FAST_HOLEY_SMI_ELEMENTS:
961
    case FAST_DOUBLE_ELEMENTS:
962
    case FAST_HOLEY_DOUBLE_ELEMENTS:
963
    case EXTERNAL_BYTE_ELEMENTS:
964
    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
965
    case EXTERNAL_SHORT_ELEMENTS:
966
    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
967
    case EXTERNAL_INT_ELEMENTS:
968
    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
969
    case EXTERNAL_FLOAT_ELEMENTS:
970
    case EXTERNAL_DOUBLE_ELEMENTS:
971
    case EXTERNAL_PIXEL_ELEMENTS:
972
      UNREACHABLE();
973
      break;
974
    case DICTIONARY_ELEMENTS:
975
      KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm);
976
      break;
977
    case NON_STRICT_ARGUMENTS_ELEMENTS:
978
      UNREACHABLE();
979
      break;
980
  }
981
}
982

    
983

    
984
void ArgumentsAccessStub::PrintName(StringStream* stream) {
985
  stream->Add("ArgumentsAccessStub_");
986
  switch (type_) {
987
    case READ_ELEMENT: stream->Add("ReadElement"); break;
988
    case NEW_NON_STRICT_FAST: stream->Add("NewNonStrictFast"); break;
989
    case NEW_NON_STRICT_SLOW: stream->Add("NewNonStrictSlow"); break;
990
    case NEW_STRICT: stream->Add("NewStrict"); break;
991
  }
992
}
993

    
994

    
995
void CallFunctionStub::PrintName(StringStream* stream) {
996
  stream->Add("CallFunctionStub_Args%d", argc_);
997
  if (ReceiverMightBeImplicit()) stream->Add("_Implicit");
998
  if (RecordCallTarget()) stream->Add("_Recording");
999
}
1000

    
1001

    
1002
void CallConstructStub::PrintName(StringStream* stream) {
1003
  stream->Add("CallConstructStub");
1004
  if (RecordCallTarget()) stream->Add("_Recording");
1005
}
1006

    
1007

    
1008
bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
1009
  Types old_types(types_);
1010
  bool to_boolean_value = types_.UpdateStatus(object);
1011
  TraceTransition(old_types, types_);
1012
  return to_boolean_value;
1013
}
1014

    
1015

    
1016
void ToBooleanStub::PrintState(StringStream* stream) {
1017
  types_.Print(stream);
1018
}
1019

    
1020

    
1021
void ToBooleanStub::Types::Print(StringStream* stream) const {
1022
  stream->Add("(");
1023
  SimpleListPrinter printer(stream);
1024
  if (IsEmpty()) printer.Add("None");
1025
  if (Contains(UNDEFINED)) printer.Add("Undefined");
1026
  if (Contains(BOOLEAN)) printer.Add("Bool");
1027
  if (Contains(NULL_TYPE)) printer.Add("Null");
1028
  if (Contains(SMI)) printer.Add("Smi");
1029
  if (Contains(SPEC_OBJECT)) printer.Add("SpecObject");
1030
  if (Contains(STRING)) printer.Add("String");
1031
  if (Contains(SYMBOL)) printer.Add("Symbol");
1032
  if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
1033
  stream->Add(")");
1034
}
1035

    
1036

    
1037
bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
1038
  if (object->IsUndefined()) {
1039
    Add(UNDEFINED);
1040
    return false;
1041
  } else if (object->IsBoolean()) {
1042
    Add(BOOLEAN);
1043
    return object->IsTrue();
1044
  } else if (object->IsNull()) {
1045
    Add(NULL_TYPE);
1046
    return false;
1047
  } else if (object->IsSmi()) {
1048
    Add(SMI);
1049
    return Smi::cast(*object)->value() != 0;
1050
  } else if (object->IsSpecObject()) {
1051
    Add(SPEC_OBJECT);
1052
    return !object->IsUndetectableObject();
1053
  } else if (object->IsString()) {
1054
    Add(STRING);
1055
    return !object->IsUndetectableObject() &&
1056
        String::cast(*object)->length() != 0;
1057
  } else if (object->IsSymbol()) {
1058
    Add(SYMBOL);
1059
    return true;
1060
  } else if (object->IsHeapNumber()) {
1061
    ASSERT(!object->IsUndetectableObject());
1062
    Add(HEAP_NUMBER);
1063
    double value = HeapNumber::cast(*object)->value();
1064
    return value != 0 && !std::isnan(value);
1065
  } else {
1066
    // We should never see an internal object at runtime here!
1067
    UNREACHABLE();
1068
    return true;
1069
  }
1070
}
1071

    
1072

    
1073
bool ToBooleanStub::Types::NeedsMap() const {
1074
  return Contains(ToBooleanStub::SPEC_OBJECT)
1075
      || Contains(ToBooleanStub::STRING)
1076
      || Contains(ToBooleanStub::SYMBOL)
1077
      || Contains(ToBooleanStub::HEAP_NUMBER);
1078
}
1079

    
1080

    
1081
bool ToBooleanStub::Types::CanBeUndetectable() const {
1082
  return Contains(ToBooleanStub::SPEC_OBJECT)
1083
      || Contains(ToBooleanStub::STRING);
1084
}
1085

    
1086

    
1087
void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) {
1088
  StubFailureTrampolineStub stub1(NOT_JS_FUNCTION_STUB_MODE);
1089
  StubFailureTrampolineStub stub2(JS_FUNCTION_STUB_MODE);
1090
  stub1.GetCode(isolate)->set_is_pregenerated(true);
1091
  stub2.GetCode(isolate)->set_is_pregenerated(true);
1092
}
1093

    
1094

    
1095
void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
1096
                                               intptr_t stack_pointer,
1097
                                               Isolate* isolate) {
1098
  FunctionEntryHook entry_hook = isolate->function_entry_hook();
1099
  ASSERT(entry_hook != NULL);
1100
  entry_hook(function, stack_pointer);
1101
}
1102

    
1103

    
1104
static void InstallDescriptor(Isolate* isolate, HydrogenCodeStub* stub) {
1105
  int major_key = stub->MajorKey();
1106
  CodeStubInterfaceDescriptor* descriptor =
1107
      isolate->code_stub_interface_descriptor(major_key);
1108
  if (!descriptor->initialized()) {
1109
    stub->InitializeInterfaceDescriptor(isolate, descriptor);
1110
  }
1111
}
1112

    
1113

    
1114
void ArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
1115
  ArrayNoArgumentConstructorStub stub1(GetInitialFastElementsKind());
1116
  InstallDescriptor(isolate, &stub1);
1117
  ArraySingleArgumentConstructorStub stub2(GetInitialFastElementsKind());
1118
  InstallDescriptor(isolate, &stub2);
1119
  ArrayNArgumentsConstructorStub stub3(GetInitialFastElementsKind());
1120
  InstallDescriptor(isolate, &stub3);
1121
}
1122

    
1123

    
1124
void NumberToStringStub::InstallDescriptors(Isolate* isolate) {
1125
  NumberToStringStub stub;
1126
  InstallDescriptor(isolate, &stub);
1127
}
1128

    
1129

    
1130
void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
1131
  FastNewClosureStub stub(STRICT_MODE, false);
1132
  InstallDescriptor(isolate, &stub);
1133
}
1134

    
1135

    
1136
ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
1137
    : argument_count_(ANY) {
1138
  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1139
}
1140

    
1141

    
1142
ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate,
1143
                                           int argument_count) {
1144
  if (argument_count == 0) {
1145
    argument_count_ = NONE;
1146
  } else if (argument_count == 1) {
1147
    argument_count_ = ONE;
1148
  } else if (argument_count >= 2) {
1149
    argument_count_ = MORE_THAN_ONE;
1150
  } else {
1151
    UNREACHABLE();
1152
  }
1153
  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1154
}
1155

    
1156

    
1157
void InternalArrayConstructorStubBase::InstallDescriptors(Isolate* isolate) {
1158
  InternalArrayNoArgumentConstructorStub stub1(FAST_ELEMENTS);
1159
  InstallDescriptor(isolate, &stub1);
1160
  InternalArraySingleArgumentConstructorStub stub2(FAST_ELEMENTS);
1161
  InstallDescriptor(isolate, &stub2);
1162
  InternalArrayNArgumentsConstructorStub stub3(FAST_ELEMENTS);
1163
  InstallDescriptor(isolate, &stub3);
1164
}
1165

    
1166
InternalArrayConstructorStub::InternalArrayConstructorStub(
1167
    Isolate* isolate) {
1168
  InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1169
}
1170

    
1171

    
1172
} }  // namespace v8::internal