~ubuntu-branches/ubuntu/saucy/libv8/saucy

« back to all changes in this revision

Viewing changes to src/ic.cc

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2012-04-07 16:26:13 UTC
  • mfrom: (15.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120407162613-dqo1m6w9r3fh8tst
Tags: 3.8.9.16-3
* mipsel build fixes :
  + v8_use_mips_abi_hardfloat=false, this lowers EABI requirements.
  + v8_can_use_fpu_instructions=false, detect if FPU is present.
  + set -Wno-unused-but-set-variable only on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2011 the V8 project authors. All rights reserved.
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
2
2
// Redistribution and use in source and binary forms, with or without
3
3
// modification, are permitted provided that the following conditions are
4
4
// met:
40
40
namespace internal {
41
41
 
42
42
#ifdef DEBUG
43
 
static char TransitionMarkFromState(IC::State state) {
 
43
char IC::TransitionMarkFromState(IC::State state) {
44
44
  switch (state) {
45
45
    case UNINITIALIZED: return '0';
46
46
    case PREMONOMORPHIC: return 'P';
47
47
    case MONOMORPHIC: return '1';
48
48
    case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
49
 
    case MEGAMORPHIC: return 'N';
 
49
    case MEGAMORPHIC: return IsGeneric() ? 'G' : 'N';
50
50
 
51
51
    // We never see the debugger states here, because the state is
52
52
    // computed from the original code - not the patched code. Let
80
80
        raw_frame = it.frame();
81
81
      }
82
82
    }
83
 
    if (raw_frame->is_java_script()) {
84
 
      JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
85
 
      Code* js_code = frame->unchecked_code();
86
 
      // Find the function on the stack and both the active code for the
87
 
      // function and the original code.
88
 
      JSFunction* function = JSFunction::cast(frame->function());
89
 
      function->PrintName();
90
 
      int code_offset =
91
 
          static_cast<int>(address() - js_code->instruction_start());
92
 
      PrintF("+%d", code_offset);
93
 
    } else {
94
 
      PrintF("<unknown>");
95
 
    }
 
83
    JavaScriptFrame::PrintTop(stdout, false, true);
96
84
    PrintF(" (%c->%c)",
97
85
           TransitionMarkFromState(old_state),
98
86
           TransitionMarkFromState(new_state));
100
88
    PrintF("]\n");
101
89
  }
102
90
}
 
91
 
 
92
#define TRACE_GENERIC_IC(type, reason)                          \
 
93
  do {                                                          \
 
94
    if (FLAG_trace_ic) {                                        \
 
95
      PrintF("[%s patching generic stub in ", type);            \
 
96
      JavaScriptFrame::PrintTop(stdout, false, true);           \
 
97
      PrintF(" (%s)]\n", reason);                               \
 
98
    }                                                           \
 
99
  } while (false)
 
100
 
 
101
#else
 
102
#define TRACE_GENERIC_IC(type, reason)
103
103
#endif  // DEBUG
104
104
 
105
 
 
106
105
#define TRACE_IC(type, name, old_state, new_target)             \
107
106
  ASSERT((TraceIC(type, name, old_state, new_target), true))
108
107
 
109
 
 
110
108
IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
111
109
  ASSERT(isolate == Isolate::Current());
112
110
  // To improve the performance of the (much used) IC code, we unfold
137
135
 
138
136
 
139
137
#ifdef ENABLE_DEBUGGER_SUPPORT
140
 
Address IC::OriginalCodeAddress() {
 
138
Address IC::OriginalCodeAddress() const {
141
139
  HandleScope scope;
142
140
  // Compute the JavaScript frame for the frame pointer of this IC
143
141
  // structure. We need this to be able to find the function
862
860
  }
863
861
 
864
862
  PropertyAttributes attr;
865
 
  if (lookup.IsProperty() &&
 
863
  if (lookup.IsFound() &&
866
864
      (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
867
865
    // Get the property.
868
866
    Handle<Object> result =
914
912
            name, receiver, holder, lookup->GetFieldIndex());
915
913
        break;
916
914
      case CONSTANT_FUNCTION: {
917
 
        Handle<Object> constant(lookup->GetConstantFunction());
 
915
        Handle<JSFunction> constant(lookup->GetConstantFunction());
918
916
        code = isolate()->stub_cache()->ComputeLoadConstant(
919
917
            name, receiver, holder, constant);
920
918
        break;
1085
1083
    }
1086
1084
 
1087
1085
    PropertyAttributes attr;
1088
 
    if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
 
1086
    if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
1089
1087
      // Get the property.
1090
1088
      Handle<Object> result =
1091
1089
          Object::GetProperty(object, object, &lookup, name, &attr);
1123
1121
          stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
1124
1122
        }
1125
1123
      }
 
1124
    } else {
 
1125
      TRACE_GENERIC_IC("KeyedLoadIC", "force generic");
1126
1126
    }
1127
1127
    if (!stub.is_null()) set_target(*stub);
1128
1128
  }
1163
1163
            name, receiver, holder, lookup->GetFieldIndex());
1164
1164
        break;
1165
1165
      case CONSTANT_FUNCTION: {
1166
 
        Handle<Object> constant(lookup->GetConstantFunction());
 
1166
        Handle<JSFunction> constant(lookup->GetConstantFunction());
1167
1167
        code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
1168
1168
            name, receiver, holder, constant);
1169
1169
        break;
1206
1206
 
1207
1207
static bool StoreICableLookup(LookupResult* lookup) {
1208
1208
  // Bail out if we didn't find a result.
1209
 
  if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;
1210
 
 
1211
 
  // If the property is read-only, we leave the IC in its current
1212
 
  // state.
 
1209
  if (!lookup->IsFound() || lookup->type() == NULL_DESCRIPTOR) return false;
 
1210
 
 
1211
  // Bail out if inline caching is not allowed.
 
1212
  if (!lookup->IsCacheable()) return false;
 
1213
 
 
1214
  // If the property is read-only, we leave the IC in its current state.
1213
1215
  if (lookup->IsReadOnly()) return false;
1214
1216
 
1215
1217
  return true;
1267
1269
  // Check if the given name is an array index.
1268
1270
  uint32_t index;
1269
1271
  if (name->AsArrayIndex(&index)) {
1270
 
    Handle<Object> result = SetElement(receiver, index, value, strict_mode);
 
1272
    Handle<Object> result =
 
1273
        JSObject::SetElement(receiver, index, value, strict_mode);
1271
1274
    RETURN_IF_EMPTY_HANDLE(isolate(), result);
1272
1275
    return *value;
1273
1276
  }
1274
1277
 
1275
 
  // Use specialized code for setting the length of arrays.
1276
 
  if (receiver->IsJSArray()
1277
 
      && name->Equals(isolate()->heap()->length_symbol())
1278
 
      && Handle<JSArray>::cast(receiver)->AllowsSetElementsLength()) {
 
1278
  // Use specialized code for setting the length of arrays with fast
 
1279
  // properties.  Slow properties might indicate redefinition of the
 
1280
  // length property.
 
1281
  if (receiver->IsJSArray() &&
 
1282
      name->Equals(isolate()->heap()->length_symbol()) &&
 
1283
      Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
 
1284
      receiver->HasFastProperties()) {
1279
1285
#ifdef DEBUG
1280
1286
    if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1281
1287
#endif
1473
1479
  // via megamorphic stubs, since they don't have a map in their relocation info
1474
1480
  // and so the stubs can't be harvested for the object needed for a map check.
1475
1481
  if (target()->type() != NORMAL) {
 
1482
    TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type");
1476
1483
    return generic_stub;
1477
1484
  }
1478
1485
 
1494
1501
  if (!map_added) {
1495
1502
    // If the miss wasn't due to an unseen map, a polymorphic stub
1496
1503
    // won't help, use the generic stub.
 
1504
    TRACE_GENERIC_IC("KeyedIC", "same map added twice");
1497
1505
    return generic_stub;
1498
1506
  }
1499
1507
 
1500
1508
  // If the maximum number of receiver maps has been exceeded, use the generic
1501
1509
  // version of the IC.
1502
1510
  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
 
1511
    TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded");
1503
1512
    return generic_stub;
1504
1513
  }
1505
1514
 
1638
1647
    // Check if the given name is an array index.
1639
1648
    uint32_t index;
1640
1649
    if (name->AsArrayIndex(&index)) {
1641
 
      Handle<Object> result = SetElement(receiver, index, value, strict_mode);
 
1650
      Handle<Object> result =
 
1651
          JSObject::SetElement(receiver, index, value, strict_mode);
1642
1652
      RETURN_IF_EMPTY_HANDLE(isolate(), result);
1643
1653
      return *value;
1644
1654
    }
1685
1695
          }
1686
1696
          stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
1687
1697
        }
 
1698
      } else {
 
1699
        TRACE_GENERIC_IC("KeyedStoreIC", "force generic");
1688
1700
      }
1689
1701
    }
1690
1702
    if (!stub.is_null()) set_target(*stub);
1874
1886
  NoHandleAllocation nha;
1875
1887
 
1876
1888
  ASSERT(args.length() == 2);
1877
 
  JSObject* receiver = JSObject::cast(args[0]);
 
1889
  JSArray* receiver = JSArray::cast(args[0]);
1878
1890
  Object* len = args[1];
1879
1891
 
1880
1892
  // The generated code should filter out non-Smis before we get here.
1881
1893
  ASSERT(len->IsSmi());
1882
1894
 
 
1895
#ifdef DEBUG
 
1896
  // The length property has to be a writable callback property.
 
1897
  LookupResult debug_lookup(isolate);
 
1898
  receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup);
 
1899
  ASSERT(debug_lookup.type() == CALLBACKS && !debug_lookup.IsReadOnly());
 
1900
#endif
 
1901
 
1883
1902
  Object* result;
1884
1903
  { MaybeObject* maybe_result = receiver->SetElementsLength(len);
1885
1904
    if (!maybe_result->ToObject(&result)) return maybe_result;
2315
2334
    case SMIS: return "SMIS";
2316
2335
    case HEAP_NUMBERS: return "HEAP_NUMBERS";
2317
2336
    case OBJECTS: return "OBJECTS";
 
2337
    case KNOWN_OBJECTS: return "OBJECTS";
2318
2338
    case SYMBOLS: return "SYMBOLS";
2319
2339
    case STRINGS: return "STRINGS";
2320
2340
    case GENERIC: return "GENERIC";
2329
2349
                                        bool has_inlined_smi_code,
2330
2350
                                        Handle<Object> x,
2331
2351
                                        Handle<Object> y) {
2332
 
  if (!has_inlined_smi_code && state != UNINITIALIZED && state != SYMBOLS) {
2333
 
    return GENERIC;
 
2352
  switch (state) {
 
2353
    case UNINITIALIZED:
 
2354
      if (x->IsSmi() && y->IsSmi()) return SMIS;
 
2355
      if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
 
2356
      if (!Token::IsEqualityOp(op_)) return GENERIC;
 
2357
      if (x->IsSymbol() && y->IsSymbol()) return SYMBOLS;
 
2358
      if (x->IsString() && y->IsString()) return STRINGS;
 
2359
      if (x->IsJSObject() && y->IsJSObject()) {
 
2360
        if (Handle<JSObject>::cast(x)->map() ==
 
2361
            Handle<JSObject>::cast(y)->map() &&
 
2362
            Token::IsEqualityOp(op_)) {
 
2363
          return KNOWN_OBJECTS;
 
2364
        } else {
 
2365
          return OBJECTS;
 
2366
        }
 
2367
      }
 
2368
      return GENERIC;
 
2369
    case SMIS:
 
2370
      return has_inlined_smi_code && x->IsNumber() && y->IsNumber()
 
2371
          ? HEAP_NUMBERS
 
2372
          : GENERIC;
 
2373
    case SYMBOLS:
 
2374
      ASSERT(Token::IsEqualityOp(op_));
 
2375
      return x->IsString() && y->IsString() ? STRINGS : GENERIC;
 
2376
    case HEAP_NUMBERS:
 
2377
    case STRINGS:
 
2378
    case OBJECTS:
 
2379
    case KNOWN_OBJECTS:
 
2380
    case GENERIC:
 
2381
      return GENERIC;
2334
2382
  }
2335
 
  if (state == UNINITIALIZED && x->IsSmi() && y->IsSmi()) return SMIS;
2336
 
  if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) &&
2337
 
      x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
2338
 
  if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC;
2339
 
  if (state == UNINITIALIZED &&
2340
 
      x->IsSymbol() && y->IsSymbol()) return SYMBOLS;
2341
 
  if ((state == UNINITIALIZED || state == SYMBOLS) &&
2342
 
      x->IsString() && y->IsString()) return STRINGS;
2343
 
  if (state == UNINITIALIZED &&
2344
 
      x->IsJSObject() && y->IsJSObject()) return OBJECTS;
 
2383
  UNREACHABLE();
2345
2384
  return GENERIC;
2346
2385
}
2347
2386