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 "ast.h"
31#include "code-stubs.h"
32#include "compiler.h"
33#include "ic.h"
34#include "macro-assembler.h"
35#include "stub-cache.h"
36#include "type-info.h"
37
38#include "ic-inl.h"
39#include "objects-inl.h"
40
41namespace v8 {
42namespace internal {
43
44
45TypeInfo TypeInfo::FromValue(Handle<Object> value) {
46  if (value->IsSmi()) {
47    return TypeInfo::Smi();
48  } else if (value->IsHeapNumber()) {
49    return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
50        ? TypeInfo::Integer32()
51        : TypeInfo::Double();
52  } else if (value->IsString()) {
53    return TypeInfo::String();
54  }
55  return TypeInfo::Unknown();
56}
57
58
59TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
60                                       Handle<Context> native_context,
61                                       Isolate* isolate,
62                                       Zone* zone)
63    : native_context_(native_context),
64      isolate_(isolate),
65      zone_(zone) {
66  BuildDictionary(code);
67  ASSERT(dictionary_->IsDictionary());
68}
69
70
71static uint32_t IdToKey(TypeFeedbackId ast_id) {
72  return static_cast<uint32_t>(ast_id.ToInt());
73}
74
75
76Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) {
77  int entry = dictionary_->FindEntry(IdToKey(ast_id));
78  if (entry != UnseededNumberDictionary::kNotFound) {
79    Object* value = dictionary_->ValueAt(entry);
80    if (value->IsCell()) {
81      Cell* cell = Cell::cast(value);
82      return Handle<Object>(cell->value(), isolate_);
83    } else {
84      return Handle<Object>(value, isolate_);
85    }
86  }
87  return Handle<Object>::cast(isolate_->factory()->undefined_value());
88}
89
90
91Handle<Cell> TypeFeedbackOracle::GetInfoCell(
92    TypeFeedbackId ast_id) {
93  int entry = dictionary_->FindEntry(IdToKey(ast_id));
94  if (entry != UnseededNumberDictionary::kNotFound) {
95    Cell* cell = Cell::cast(dictionary_->ValueAt(entry));
96    return Handle<Cell>(cell, isolate_);
97  }
98  return Handle<Cell>::null();
99}
100
101
102bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) {
103  Handle<Object> maybe_code = GetInfo(id);
104  if (maybe_code->IsCode()) {
105    Handle<Code> code = Handle<Code>::cast(maybe_code);
106    return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED;
107  }
108  return false;
109}
110
111
112bool TypeFeedbackOracle::LoadIsPreMonomorphic(TypeFeedbackId id) {
113  Handle<Object> maybe_code = GetInfo(id);
114  if (maybe_code->IsCode()) {
115    Handle<Code> code = Handle<Code>::cast(maybe_code);
116    return code->is_inline_cache_stub() && code->ic_state() == PREMONOMORPHIC;
117  }
118  return false;
119}
120
121
122bool TypeFeedbackOracle::StoreIsUninitialized(TypeFeedbackId ast_id) {
123  Handle<Object> maybe_code = GetInfo(ast_id);
124  if (!maybe_code->IsCode()) return false;
125  Handle<Code> code = Handle<Code>::cast(maybe_code);
126  return code->ic_state() == UNINITIALIZED;
127}
128
129
130bool TypeFeedbackOracle::StoreIsPreMonomorphic(TypeFeedbackId ast_id) {
131  Handle<Object> maybe_code = GetInfo(ast_id);
132  if (maybe_code->IsCode()) {
133    Handle<Code> code = Handle<Code>::cast(maybe_code);
134    return code->ic_state() == PREMONOMORPHIC;
135  }
136  return false;
137}
138
139
140bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) {
141  Handle<Object> maybe_code = GetInfo(ast_id);
142  if (maybe_code->IsCode()) {
143    Handle<Code> code = Handle<Code>::cast(maybe_code);
144    return code->is_keyed_store_stub() &&
145        code->ic_state() == POLYMORPHIC;
146  }
147  return false;
148}
149
150
151bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) {
152  Handle<Object> value = GetInfo(id);
153  return value->IsAllocationSite() || value->IsJSFunction() || value->IsSmi() ||
154      (value->IsCode() && Handle<Code>::cast(value)->ic_state() == MONOMORPHIC);
155}
156
157
158bool TypeFeedbackOracle::KeyedArrayCallIsHoley(TypeFeedbackId id) {
159  Handle<Object> value = GetInfo(id);
160  Handle<Code> code = Handle<Code>::cast(value);
161  return KeyedArrayCallStub::IsHoley(code);
162}
163
164
165bool TypeFeedbackOracle::CallNewIsMonomorphic(TypeFeedbackId id) {
166  Handle<Object> info = GetInfo(id);
167  return info->IsAllocationSite() || info->IsJSFunction();
168}
169
170
171byte TypeFeedbackOracle::ForInType(TypeFeedbackId id) {
172  Handle<Object> value = GetInfo(id);
173  return value->IsSmi() &&
174      Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker
175          ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN;
176}
177
178
179KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode(
180    TypeFeedbackId ast_id) {
181  Handle<Object> maybe_code = GetInfo(ast_id);
182  if (maybe_code->IsCode()) {
183    Handle<Code> code = Handle<Code>::cast(maybe_code);
184    if (code->kind() == Code::KEYED_STORE_IC) {
185      return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state());
186    }
187  }
188  return STANDARD_STORE;
189}
190
191
192void TypeFeedbackOracle::CallReceiverTypes(TypeFeedbackId id,
193                                           Handle<String> name,
194                                           int arity,
195                                           CallKind call_kind,
196                                           SmallMapList* types) {
197  // Note: Currently we do not take string extra ic data into account
198  // here.
199  ContextualMode contextual_mode = call_kind == CALL_AS_FUNCTION
200      ? CONTEXTUAL
201      : NOT_CONTEXTUAL;
202  ExtraICState extra_ic_state =
203      CallIC::Contextual::encode(contextual_mode);
204
205  Code::Flags flags = Code::ComputeMonomorphicFlags(
206      Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity);
207  CollectReceiverTypes(id, name, flags, types);
208}
209
210
211CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) {
212  Handle<Object> value = GetInfo(id);
213  if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
214  CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
215  ASSERT(check != RECEIVER_MAP_CHECK);
216  return check;
217}
218
219
220Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) {
221  Handle<Object> info = GetInfo(id);
222  if (info->IsAllocationSite()) {
223    return Handle<JSFunction>(isolate_->global_context()->array_function());
224  } else {
225    return Handle<JSFunction>::cast(info);
226  }
227}
228
229
230Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) {
231  Handle<Object> info = GetInfo(id);
232  if (info->IsAllocationSite()) {
233    return Handle<JSFunction>(isolate_->global_context()->array_function());
234  } else {
235    return Handle<JSFunction>::cast(info);
236  }
237}
238
239
240Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(
241    TypeFeedbackId id) {
242  return GetInfoCell(id);
243}
244
245
246bool TypeFeedbackOracle::LoadIsBuiltin(
247    TypeFeedbackId id, Builtins::Name builtin) {
248  return *GetInfo(id) == isolate_->builtins()->builtin(builtin);
249}
250
251
252bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) {
253  Handle<Object> object = GetInfo(id);
254  if (!object->IsCode()) return false;
255  Handle<Code> code = Handle<Code>::cast(object);
256  if (!code->is_load_stub()) return false;
257  if (code->ic_state() != MONOMORPHIC) return false;
258  return stub->Describes(*code);
259}
260
261
262void TypeFeedbackOracle::CompareType(TypeFeedbackId id,
263                                     Handle<Type>* left_type,
264                                     Handle<Type>* right_type,
265                                     Handle<Type>* combined_type) {
266  Handle<Object> info = GetInfo(id);
267  if (!info->IsCode()) {
268    // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof.
269    *left_type = *right_type = *combined_type = handle(Type::None(), isolate_);
270    return;
271  }
272  Handle<Code> code = Handle<Code>::cast(info);
273
274  Handle<Map> map;
275  Map* raw_map = code->FindFirstMap();
276  if (raw_map != NULL) {
277    map = Map::CurrentMapForDeprecated(handle(raw_map));
278    if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) {
279      map = Handle<Map>::null();
280    }
281  }
282
283  if (code->is_compare_ic_stub()) {
284    int stub_minor_key = code->stub_info();
285    CompareIC::StubInfoToType(
286        stub_minor_key, left_type, right_type, combined_type, map, isolate());
287  } else if (code->is_compare_nil_ic_stub()) {
288    CompareNilICStub stub(code->extended_extra_ic_state());
289    *combined_type = stub.GetType(isolate_, map);
290    *left_type = *right_type = stub.GetInputType(isolate_, map);
291  }
292}
293
294
295void TypeFeedbackOracle::BinaryType(TypeFeedbackId id,
296                                    Handle<Type>* left,
297                                    Handle<Type>* right,
298                                    Handle<Type>* result,
299                                    Maybe<int>* fixed_right_arg,
300                                    Token::Value op) {
301  Handle<Object> object = GetInfo(id);
302  if (!object->IsCode()) {
303    // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the
304    // operations covered by the BinaryOpIC we should always have them.
305    ASSERT(op < BinaryOpIC::State::FIRST_TOKEN ||
306           op > BinaryOpIC::State::LAST_TOKEN);
307    *left = *right = *result = handle(Type::None(), isolate_);
308    *fixed_right_arg = Maybe<int>();
309    return;
310  }
311  Handle<Code> code = Handle<Code>::cast(object);
312  ASSERT_EQ(Code::BINARY_OP_IC, code->kind());
313  BinaryOpIC::State state(code->extended_extra_ic_state());
314  ASSERT_EQ(op, state.op());
315
316  *left = state.GetLeftType(isolate());
317  *right = state.GetRightType(isolate());
318  *result = state.GetResultType(isolate());
319  *fixed_right_arg = state.fixed_right_arg();
320}
321
322
323Handle<Type> TypeFeedbackOracle::ClauseType(TypeFeedbackId id) {
324  Handle<Object> info = GetInfo(id);
325  Handle<Type> result(Type::None(), isolate_);
326  if (info->IsCode() && Handle<Code>::cast(info)->is_compare_ic_stub()) {
327    Handle<Code> code = Handle<Code>::cast(info);
328    CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
329    result = CompareIC::StateToType(isolate_, state);
330  }
331  return result;
332}
333
334
335Handle<Type> TypeFeedbackOracle::CountType(TypeFeedbackId id) {
336  Handle<Object> object = GetInfo(id);
337  if (!object->IsCode()) return handle(Type::None(), isolate_);
338  Handle<Code> code = Handle<Code>::cast(object);
339  ASSERT_EQ(Code::BINARY_OP_IC, code->kind());
340  BinaryOpIC::State state(code->extended_extra_ic_state());
341  return state.GetLeftType(isolate());
342}
343
344
345void TypeFeedbackOracle::PropertyReceiverTypes(
346    TypeFeedbackId id, Handle<String> name,
347    SmallMapList* receiver_types, bool* is_prototype) {
348  receiver_types->Clear();
349  FunctionPrototypeStub proto_stub(Code::LOAD_IC);
350  *is_prototype = LoadIsStub(id, &proto_stub);
351  if (!*is_prototype) {
352    Code::Flags flags = Code::ComputeFlags(
353        Code::HANDLER, MONOMORPHIC, kNoExtraICState,
354        Code::NORMAL, Code::LOAD_IC);
355    CollectReceiverTypes(id, name, flags, receiver_types);
356  }
357}
358
359
360void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
361    TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) {
362  receiver_types->Clear();
363  *is_string = false;
364  if (LoadIsBuiltin(id, Builtins::kKeyedLoadIC_String)) {
365    *is_string = true;
366  } else {
367    CollectReceiverTypes(id, receiver_types);
368  }
369}
370
371
372void TypeFeedbackOracle::AssignmentReceiverTypes(
373    TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) {
374  receiver_types->Clear();
375  Code::Flags flags = Code::ComputeFlags(
376      Code::HANDLER, MONOMORPHIC, kNoExtraICState,
377      Code::NORMAL, Code::STORE_IC);
378  CollectReceiverTypes(id, name, flags, receiver_types);
379}
380
381
382void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
383    TypeFeedbackId id, SmallMapList* receiver_types,
384    KeyedAccessStoreMode* store_mode) {
385  receiver_types->Clear();
386  CollectReceiverTypes(id, receiver_types);
387  *store_mode = GetStoreMode(id);
388}
389
390
391void TypeFeedbackOracle::CountReceiverTypes(TypeFeedbackId id,
392                                            SmallMapList* receiver_types) {
393  receiver_types->Clear();
394  CollectReceiverTypes(id, receiver_types);
395}
396
397
398void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
399                                              Handle<String> name,
400                                              Code::Flags flags,
401                                              SmallMapList* types) {
402  Handle<Object> object = GetInfo(ast_id);
403  if (object->IsUndefined() || object->IsSmi()) return;
404
405  ASSERT(object->IsCode());
406  Handle<Code> code(Handle<Code>::cast(object));
407
408  if (FLAG_collect_megamorphic_maps_from_stub_cache &&
409      code->ic_state() == MEGAMORPHIC) {
410    types->Reserve(4, zone());
411    isolate_->stub_cache()->CollectMatchingMaps(
412        types, name, flags, native_context_, zone());
413  } else {
414    CollectReceiverTypes(ast_id, types);
415  }
416}
417
418
419// Check if a map originates from a given native context. We use this
420// information to filter out maps from different context to avoid
421// retaining objects from different tabs in Chrome via optimized code.
422bool TypeFeedbackOracle::CanRetainOtherContext(Map* map,
423                                               Context* native_context) {
424  Object* constructor = NULL;
425  while (!map->prototype()->IsNull()) {
426    constructor = map->constructor();
427    if (!constructor->IsNull()) {
428      // If the constructor is not null or a JSFunction, we have to
429      // conservatively assume that it may retain a native context.
430      if (!constructor->IsJSFunction()) return true;
431      // Check if the constructor directly references a foreign context.
432      if (CanRetainOtherContext(JSFunction::cast(constructor),
433                                native_context)) {
434        return true;
435      }
436    }
437    map = HeapObject::cast(map->prototype())->map();
438  }
439  constructor = map->constructor();
440  if (constructor->IsNull()) return false;
441  JSFunction* function = JSFunction::cast(constructor);
442  return CanRetainOtherContext(function, native_context);
443}
444
445
446bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function,
447                                               Context* native_context) {
448  return function->context()->global_object() != native_context->global_object()
449      && function->context()->global_object() != native_context->builtins();
450}
451
452
453void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id,
454                                              SmallMapList* types) {
455  Handle<Object> object = GetInfo(ast_id);
456  if (!object->IsCode()) return;
457  Handle<Code> code = Handle<Code>::cast(object);
458  MapHandleList maps;
459  if (code->ic_state() == MONOMORPHIC) {
460    Map* map = code->FindFirstMap();
461    if (map != NULL) maps.Add(handle(map));
462  } else if (code->ic_state() == POLYMORPHIC) {
463    code->FindAllMaps(&maps);
464  } else {
465    return;
466  }
467  types->Reserve(maps.length(), zone());
468  for (int i = 0; i < maps.length(); i++) {
469    Handle<Map> map(maps.at(i));
470    if (!CanRetainOtherContext(*map, *native_context_)) {
471      types->AddMapIfMissing(map, zone());
472    }
473  }
474}
475
476
477byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) {
478  Handle<Object> object = GetInfo(id);
479  return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
480}
481
482
483// Things are a bit tricky here: The iterator for the RelocInfos and the infos
484// themselves are not GC-safe, so we first get all infos, then we create the
485// dictionary (possibly triggering GC), and finally we relocate the collected
486// infos before we process them.
487void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) {
488  DisallowHeapAllocation no_allocation;
489  ZoneList<RelocInfo> infos(16, zone());
490  HandleScope scope(isolate_);
491  GetRelocInfos(code, &infos);
492  CreateDictionary(code, &infos);
493  ProcessRelocInfos(&infos);
494  ProcessTypeFeedbackCells(code);
495  // Allocate handle in the parent scope.
496  dictionary_ = scope.CloseAndEscape(dictionary_);
497}
498
499
500void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code,
501                                       ZoneList<RelocInfo>* infos) {
502  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
503  for (RelocIterator it(*code, mask); !it.done(); it.next()) {
504    infos->Add(*it.rinfo(), zone());
505  }
506}
507
508
509void TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
510                                          ZoneList<RelocInfo>* infos) {
511  AllowHeapAllocation allocation_allowed;
512  int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo()
513      ? TypeFeedbackInfo::cast(code->type_feedback_info())->
514          type_feedback_cells()->CellCount()
515      : 0;
516  int length = infos->length() + cell_count;
517  byte* old_start = code->instruction_start();
518  dictionary_ = isolate()->factory()->NewUnseededNumberDictionary(length);
519  byte* new_start = code->instruction_start();
520  RelocateRelocInfos(infos, old_start, new_start);
521}
522
523
524void TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos,
525                                            byte* old_start,
526                                            byte* new_start) {
527  for (int i = 0; i < infos->length(); i++) {
528    RelocInfo* info = &(*infos)[i];
529    info->set_pc(new_start + (info->pc() - old_start));
530  }
531}
532
533
534void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
535  for (int i = 0; i < infos->length(); i++) {
536    RelocInfo reloc_entry = (*infos)[i];
537    Address target_address = reloc_entry.target_address();
538    TypeFeedbackId ast_id =
539        TypeFeedbackId(static_cast<unsigned>((*infos)[i].data()));
540    Code* target = Code::GetCodeFromTargetAddress(target_address);
541    switch (target->kind()) {
542      case Code::CALL_IC:
543        if (target->ic_state() == MONOMORPHIC &&
544            target->check_type() != RECEIVER_MAP_CHECK) {
545          SetInfo(ast_id, Smi::FromInt(target->check_type()));
546          break;
547        }
548      case Code::LOAD_IC:
549      case Code::STORE_IC:
550      case Code::KEYED_CALL_IC:
551      case Code::KEYED_LOAD_IC:
552      case Code::KEYED_STORE_IC:
553      case Code::BINARY_OP_IC:
554      case Code::COMPARE_IC:
555      case Code::TO_BOOLEAN_IC:
556      case Code::COMPARE_NIL_IC:
557        SetInfo(ast_id, target);
558        break;
559
560      default:
561        break;
562    }
563  }
564}
565
566
567void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) {
568  Object* raw_info = code->type_feedback_info();
569  if (!raw_info->IsTypeFeedbackInfo()) return;
570  Handle<TypeFeedbackCells> cache(
571      TypeFeedbackInfo::cast(raw_info)->type_feedback_cells());
572  for (int i = 0; i < cache->CellCount(); i++) {
573    TypeFeedbackId ast_id = cache->AstId(i);
574    Cell* cell = cache->GetCell(i);
575    Object* value = cell->value();
576    if (value->IsSmi() ||
577        value->IsAllocationSite() ||
578        (value->IsJSFunction() &&
579         !CanRetainOtherContext(JSFunction::cast(value),
580                                *native_context_))) {
581      SetInfo(ast_id, cell);
582    }
583  }
584}
585
586
587void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) {
588  ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) ==
589         UnseededNumberDictionary::kNotFound);
590  MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target);
591  USE(maybe_result);
592#ifdef DEBUG
593  Object* result = NULL;
594  // Dictionary has been allocated with sufficient size for all elements.
595  ASSERT(maybe_result->ToObject(&result));
596  ASSERT(*dictionary_ == result);
597#endif
598}
599
600
601Representation Representation::FromType(TypeInfo info) {
602  if (info.IsUninitialized()) return Representation::None();
603  if (info.IsSmi()) return Representation::Smi();
604  if (info.IsInteger32()) return Representation::Integer32();
605  if (info.IsDouble()) return Representation::Double();
606  if (info.IsNumber()) return Representation::Double();
607  return Representation::Tagged();
608}
609
610
611} }  // namespace v8::internal
612