Revision f230a1cf deps/v8/src/code-stubs.cc

View differences:

deps/v8/src/code-stubs.cc
41 41

  
42 42
CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
43 43
    : register_param_count_(-1),
44
      stack_parameter_count_(NULL),
44
      stack_parameter_count_(no_reg),
45 45
      hint_stack_parameter_count_(-1),
46 46
      function_mode_(NOT_JS_FUNCTION_STUB_MODE),
47 47
      register_params_(NULL),
......
129 129
}
130 130

  
131 131

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

  
136

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

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

  
143 153
  {
144 154
    HandleScope scope(isolate);
145 155

  
......
203 213
}
204 214

  
205 215

  
206
void BinaryOpStub::Generate(MacroAssembler* masm) {
207
  // Explicitly allow generation of nested stubs. It is safe here because
208
  // generation code does not use any raw pointers.
209
  AllowStubCallsScope allow_stub_calls(masm, true);
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

  
210 224

  
211
  BinaryOpIC::TypeInfo operands_type = Max(left_type_, right_type_);
212
  if (left_type_ == BinaryOpIC::ODDBALL && right_type_ == BinaryOpIC::ODDBALL) {
213
    // The OddballStub handles a number and an oddball, not two oddballs.
214
    operands_type = BinaryOpIC::GENERIC;
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_));
215 233
  }
216
  switch (operands_type) {
217
    case BinaryOpIC::UNINITIALIZED:
218
      GenerateTypeTransition(masm);
219
      break;
220
    case BinaryOpIC::SMI:
221
      GenerateSmiStub(masm);
222
      break;
223
    case BinaryOpIC::INT32:
224
      GenerateInt32Stub(masm);
225
      break;
226
    case BinaryOpIC::NUMBER:
227
      GenerateNumberStub(masm);
228
      break;
229
    case BinaryOpIC::ODDBALL:
230
      GenerateOddballStub(masm);
231
      break;
232
    case BinaryOpIC::STRING:
233
      GenerateStringStub(masm);
234
      break;
235
    case BinaryOpIC::GENERIC:
236
      GenerateGeneric(masm);
237
      break;
238
    default:
239
      UNREACHABLE();
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);
240 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);
241 501
}
242 502

  
243 503

  
244
#define __ ACCESS_MASM(masm)
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
}
245 508

  
246 509

  
247
void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
248
  switch (op_) {
249
    case Token::ADD:
250
      __ InvokeBuiltin(Builtins::ADD, CALL_FUNCTION);
251
      break;
252
    case Token::SUB:
253
      __ InvokeBuiltin(Builtins::SUB, CALL_FUNCTION);
254
      break;
255
    case Token::MUL:
256
      __ InvokeBuiltin(Builtins::MUL, CALL_FUNCTION);
257
      break;
258
    case Token::DIV:
259
      __ InvokeBuiltin(Builtins::DIV, CALL_FUNCTION);
260
      break;
261
    case Token::MOD:
262
      __ InvokeBuiltin(Builtins::MOD, CALL_FUNCTION);
263
      break;
264
    case Token::BIT_OR:
265
      __ InvokeBuiltin(Builtins::BIT_OR, CALL_FUNCTION);
266
      break;
267
    case Token::BIT_AND:
268
      __ InvokeBuiltin(Builtins::BIT_AND, CALL_FUNCTION);
269
      break;
270
    case Token::BIT_XOR:
271
      __ InvokeBuiltin(Builtins::BIT_XOR, CALL_FUNCTION);
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);
272 645
      break;
273
    case Token::SAR:
274
      __ InvokeBuiltin(Builtins::SAR, CALL_FUNCTION);
646

  
647
    case STRING:
648
      t = handle(Type::Union(t, handle(Type::String(), isolate)), isolate);
275 649
      break;
276
    case Token::SHR:
277
      __ InvokeBuiltin(Builtins::SHR, CALL_FUNCTION);
650
    case GENERIC:
651
      return handle(Type::Any(), isolate);
278 652
      break;
279
    case Token::SHL:
280
      __ InvokeBuiltin(Builtins::SHL, CALL_FUNCTION);
653
    case NONE:
281 654
      break;
282
    default:
283
      UNREACHABLE();
284 655
  }
656
  return t;
285 657
}
286 658

  
287 659

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

  
290 664

  
291
void BinaryOpStub::PrintName(StringStream* stream) {
292
  const char* op_name = Token::Name(op_);
293
  const char* overwrite_name;
294
  switch (mode_) {
295
    case NO_OVERWRITE: overwrite_name = "Alloc"; break;
296
    case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
297
    case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
298
    default: overwrite_name = "UnknownOverwrite"; break;
299
  }
300
  stream->Add("BinaryOpStub_%s_%s_%s+%s",
301
              op_name,
302
              overwrite_name,
303
              BinaryOpIC::GetName(left_type_),
304
              BinaryOpIC::GetName(right_type_));
665
Handle<Type> BinaryOpStub::GetRightType(Isolate* isolate) const {
666
  return StateToType(right_state_, isolate);
305 667
}
306 668

  
307 669

  
308
void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
309
  ASSERT(left_type_ == BinaryOpIC::STRING || right_type_ == BinaryOpIC::STRING);
310
  ASSERT(op_ == Token::ADD);
311
  if (left_type_ == BinaryOpIC::STRING && right_type_ == BinaryOpIC::STRING) {
312
    GenerateBothStringStub(masm);
313
    return;
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);
314 679
  }
315
  // Try to add arguments as strings, otherwise, transition to the generic
316
  // BinaryOpIC type.
317
  GenerateAddStrings(masm);
318
  GenerateTypeTransition(masm);
680
  return StateToType(result_state_, isolate);
319 681
}
320 682

  
321 683

  
......
759 1121
}
760 1122

  
761 1123

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

  
1129

  
762 1130
void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
763 1131
  FastNewClosureStub stub(STRICT_MODE, false);
764 1132
  InstallDescriptor(isolate, &stub);

Also available in: Unified diff