13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "v8.h"
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ast.h"
313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "code-stubs.h"
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "compiler.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ic.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "macro-assembler.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "stub-cache.h"
366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "type-info.h"
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ic-inl.h"
396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "objects-inl.h"
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
456ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockTypeInfo TypeInfo::TypeFromValue(Handle<Object> value) {
466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  TypeInfo info;
476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (value->IsSmi()) {
486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info = TypeInfo::Smi();
496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (value->IsHeapNumber()) {
506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        ? TypeInfo::Integer32()
526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        : TypeInfo::Double();
536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (value->IsString()) {
546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info = TypeInfo::String();
556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info = TypeInfo::Unknown();
576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return info;
596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochTypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Handle<Context> global_context,
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Isolate* isolate) {
65b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  global_context_ = global_context;
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate_ = isolate;
673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  BuildDictionary(code);
6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue);
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHandle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) {
73257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int entry = dictionary_->FindEntry(ast_id);
74c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  return entry != UnseededNumberDictionary::kNotFound
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ? Handle<Object>(dictionary_->ValueAt(entry))
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : Handle<Object>::cast(isolate_->factory()->undefined_value());
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) {
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(expr->id());
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (map_or_code->IsMap()) return false;
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (map_or_code->IsCode()) {
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code = Handle<Code>::cast(map_or_code);
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED;
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) {
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(expr->id());
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (map_or_code->IsMap()) return true;
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (map_or_code->IsCode()) {
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> code = Handle<Code>::cast(map_or_code);
96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return code->is_keyed_load_stub() &&
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        code->ic_state() == MONOMORPHIC &&
983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Code::ExtractTypeFromFlags(code->flags()) == NORMAL &&
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        code->FindFirstMap() != NULL &&
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        !CanRetainOtherContext(code->FindFirstMap(), *global_context_);
10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return false;
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) {
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(expr->id());
1083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (map_or_code->IsCode()) {
1093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Handle<Code> code = Handle<Code>::cast(map_or_code);
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Builtins* builtins = isolate_->builtins();
1113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return code->is_keyed_load_stub() &&
1123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) &&
1133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        code->ic_state() == MEGAMORPHIC;
1143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return false;
1163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
1173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) {
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(expr->id());
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (map_or_code->IsMap()) return true;
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (map_or_code->IsCode()) {
123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> code = Handle<Code>::cast(map_or_code);
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool allow_growth =
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Code::GetKeyedAccessGrowMode(code->extra_ic_state()) ==
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ALLOW_JSARRAY_GROWTH;
127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return code->is_keyed_store_stub() &&
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        !allow_growth &&
1293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        code->ic_state() == MONOMORPHIC &&
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Code::ExtractTypeFromFlags(code->flags()) == NORMAL &&
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        code->FindFirstMap() != NULL &&
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        !CanRetainOtherContext(code->FindFirstMap(), *global_context_);
1333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return false;
1353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(Expression* expr) {
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(expr->id());
1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (map_or_code->IsCode()) {
1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Handle<Code> code = Handle<Code>::cast(map_or_code);
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Builtins* builtins = isolate_->builtins();
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool allow_growth =
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Code::GetKeyedAccessGrowMode(code->extra_ic_state()) ==
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ALLOW_JSARRAY_GROWTH;
1463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return code->is_keyed_store_stub() &&
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        !allow_growth &&
1483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic) &&
1493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic_Strict) &&
1503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        code->ic_state() == MEGAMORPHIC;
15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return false;
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> value = GetInfo(expr->id());
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return value->IsMap() || value->IsSmi() || value->IsJSFunction();
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) {
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> value = GetInfo(expr->id());
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return value->IsJSFunction();
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic(
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ObjectLiteral::Property* prop) {
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(prop->key()->id());
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return map_or_code->IsMap();
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool TypeFeedbackOracle::IsForInFastCase(ForInStatement* stmt) {
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> value = GetInfo(stmt->PrepareId());
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return value->IsSmi() &&
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker;
1795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
1805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHandle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(LoadIsMonomorphicNormal(expr));
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(expr->id());
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (map_or_code->IsCode()) {
186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> code = Handle<Code>::cast(map_or_code);
187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Map* first_map = code->FindFirstMap();
188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ASSERT(first_map != NULL);
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return CanRetainOtherContext(first_map, *global_context_)
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? Handle<Map>::null()
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : Handle<Map>(first_map);
19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Handle<Map>::cast(map_or_code);
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1978b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHandle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) {
1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(StoreIsMonomorphicNormal(expr));
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> map_or_code = GetInfo(expr->id());
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (map_or_code->IsCode()) {
201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<Code> code = Handle<Code>::cast(map_or_code);
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Map* first_map = code->FindFirstMap();
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(first_map != NULL);
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return CanRetainOtherContext(first_map, *global_context_)
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? Handle<Map>::null()
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : Handle<Map>(first_map);
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return Handle<Map>::cast(map_or_code);
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
21269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
21369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           Handle<String> name,
21469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           SmallMapList* types) {
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
21669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CollectReceiverTypes(expr->id(), name, flags, types);
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
22169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                            Handle<String> name,
22269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                            SmallMapList* types) {
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
22469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CollectReceiverTypes(expr->id(), name, flags, types);
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid TypeFeedbackOracle::CallReceiverTypes(Call* expr,
22969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           Handle<String> name,
23069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           CallKind call_kind,
23169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           SmallMapList* types) {
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int arity = expr->arguments()->length();
233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Note: Currently we do not take string extra ic data into account
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // here.
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Code::ExtraICState extra_ic_state =
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION);
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
239b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
240b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                    NORMAL,
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                                    extra_ic_state,
242b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                    OWN_MAP,
243b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                    arity);
24469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CollectReceiverTypes(expr->id(), name, flags, types);
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
248b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochCheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> value = GetInfo(expr->id());
250b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
251b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
252b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(check != RECEIVER_MAP_CHECK);
253b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  return check;
254b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
255b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
257b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochHandle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
258b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    CheckType check) {
259b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  JSFunction* function = NULL;
260b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  switch (check) {
261b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    case RECEIVER_MAP_CHECK:
262b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      UNREACHABLE();
263b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      break;
264b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    case STRING_CHECK:
265b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      function = global_context_->string_function();
266b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      break;
267b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    case NUMBER_CHECK:
268b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      function = global_context_->number_function();
269b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      break;
270b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    case BOOLEAN_CHECK:
271b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      function = global_context_->boolean_function();
272b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      break;
273b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(function != NULL);
275b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
278b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) {
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Handle<JSFunction>::cast(GetInfo(expr->id()));
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) {
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Handle<JSFunction>::cast(GetInfo(expr->id()));
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap(
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ObjectLiteral::Property* prop) {
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ObjectLiteralStoreIsMonomorphic(prop));
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Handle<Map>::cast(GetInfo(prop->key()->id()));
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return *GetInfo(expr->id()) ==
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate_->builtins()->builtin(id);
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3021e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> object = GetInfo(expr->id());
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeInfo unknown = TypeInfo::Unknown();
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!object->IsCode()) return unknown;
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Code> code = Handle<Code>::cast(object);
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!code->is_compare_ic_stub()) return unknown;
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (state) {
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::UNINITIALIZED:
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Uninitialized means never executed.
3133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return TypeInfo::Uninitialized();
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::SMIS:
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return TypeInfo::Smi();
316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::HEAP_NUMBERS:
317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return TypeInfo::Number();
318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case CompareIC::SYMBOLS:
319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case CompareIC::STRINGS:
320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return TypeInfo::String();
321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::OBJECTS:
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CompareIC::KNOWN_OBJECTS:
323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // TODO(kasperl): We really need a type for JS objects here.
324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return TypeInfo::NonPrimitive();
325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::GENERIC:
326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return unknown;
328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool TypeFeedbackOracle::IsSymbolCompare(CompareOperation* expr) {
333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> object = GetInfo(expr->id());
334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!object->IsCode()) return false;
335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> code = Handle<Code>::cast(object);
336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!code->is_compare_ic_stub()) return false;
337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return state == CompareIC::SYMBOLS;
339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) {
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> object = GetInfo(expr->id());
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!object->IsCode()) return Handle<Map>::null();
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Code> code = Handle<Code>::cast(object);
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!code->is_compare_ic_stub()) return Handle<Map>::null();
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (state != CompareIC::KNOWN_OBJECTS) {
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Handle<Map>::null();
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Map* first_map = code->FindFirstMap();
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(first_map != NULL);
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return CanRetainOtherContext(first_map, *global_context_)
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? Handle<Map>::null()
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : Handle<Map>(first_map);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) {
360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> object = GetInfo(expr->id());
361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TypeInfo unknown = TypeInfo::Unknown();
362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!object->IsCode()) return unknown;
363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> code = Handle<Code>::cast(object);
364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ASSERT(code->is_unary_op_stub());
365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>(
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      code->unary_op_type());
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch (type) {
368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case UnaryOpIC::SMI:
369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return TypeInfo::Smi();
370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case UnaryOpIC::HEAP_NUMBER:
371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return TypeInfo::Double();
372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    default:
373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return unknown;
374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3781e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockTypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) {
379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> object = GetInfo(expr->id());
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeInfo unknown = TypeInfo::Unknown();
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!object->IsCode()) return unknown;
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Code> code = Handle<Code>::cast(object);
383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (code->is_binary_op_stub()) {
384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        code->binary_op_type());
386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>(
387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        code->binary_op_result_type());
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    switch (type) {
390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case BinaryOpIC::UNINITIALIZED:
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Uninitialized means never executed.
3923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return TypeInfo::Uninitialized();
393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case BinaryOpIC::SMI:
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        switch (result_type) {
395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          case BinaryOpIC::UNINITIALIZED:
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            if (expr->op() == Token::DIV) {
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              return TypeInfo::Double();
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return TypeInfo::Smi();
400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          case BinaryOpIC::SMI:
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return TypeInfo::Smi();
402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          case BinaryOpIC::INT32:
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return TypeInfo::Integer32();
404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          case BinaryOpIC::HEAP_NUMBER:
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return TypeInfo::Double();
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          default:
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return unknown;
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case BinaryOpIC::INT32:
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (expr->op() == Token::DIV ||
411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            result_type == BinaryOpIC::HEAP_NUMBER) {
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          return TypeInfo::Double();
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return TypeInfo::Integer32();
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case BinaryOpIC::HEAP_NUMBER:
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return TypeInfo::Double();
417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case BinaryOpIC::BOTH_STRING:
418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return TypeInfo::String();
419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case BinaryOpIC::STRING:
420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      case BinaryOpIC::GENERIC:
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return unknown;
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     default:
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return unknown;
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return unknown;
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
429b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> object = GetInfo(clause->CompareId());
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TypeInfo unknown = TypeInfo::Unknown();
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!object->IsCode()) return unknown;
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<Code> code = Handle<Code>::cast(object);
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!code->is_compare_ic_stub()) return unknown;
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (state) {
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::UNINITIALIZED:
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Uninitialized means never executed.
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // TODO(fschneider): Introduce a separate value for never-executed ICs.
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return unknown;
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::SMIS:
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return TypeInfo::Smi();
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CompareIC::STRINGS:
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return TypeInfo::String();
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CompareIC::SYMBOLS:
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return TypeInfo::Symbol();
449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::HEAP_NUMBERS:
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return TypeInfo::Number();
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::OBJECTS:
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case CompareIC::KNOWN_OBJECTS:
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // TODO(kasperl): We really need a type for JS objects here.
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return TypeInfo::NonPrimitive();
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case CompareIC::GENERIC:
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return unknown;
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> object = GetInfo(expr->CountId());
464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  TypeInfo unknown = TypeInfo::Unknown();
465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!object->IsCode()) return unknown;
466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Code> code = Handle<Code>::cast(object);
467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (!code->is_binary_op_stub()) return unknown;
468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      code->binary_op_type());
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  switch (type) {
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case BinaryOpIC::UNINITIALIZED:
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case BinaryOpIC::SMI:
474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return TypeInfo::Smi();
475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case BinaryOpIC::INT32:
476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return TypeInfo::Integer32();
477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case BinaryOpIC::HEAP_NUMBER:
478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return TypeInfo::Double();
479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case BinaryOpIC::BOTH_STRING:
480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case BinaryOpIC::STRING:
481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    case BinaryOpIC::GENERIC:
482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return unknown;
483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    default:
484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      return unknown;
485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  UNREACHABLE();
487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return unknown;
488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
49169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id,
49269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                              Handle<String> name,
49369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                              Code::Flags flags,
49469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                              SmallMapList* types) {
495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Handle<Object> object = GetInfo(ast_id);
49669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (object->IsUndefined() || object->IsSmi()) return;
497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (*object ==
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) {
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(fschneider): We could collect the maps and signal that
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // we need a generic store (or load) here.
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (object->IsMap()) {
504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    types->Add(Handle<Map>::cast(object));
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (FLAG_collect_megamorphic_maps_from_stub_cache &&
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
50769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    types->Reserve(4);
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(object->IsCode());
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    isolate_->stub_cache()->CollectMatchingMaps(types,
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                *name,
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                flags,
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                global_context_);
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Check if a map originates from a given global context. We use this
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// information to filter out maps from different context to avoid
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// retaining objects from different tabs in Chrome via optimized code.
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool TypeFeedbackOracle::CanRetainOtherContext(Map* map,
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Context* global_context) {
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object* constructor = NULL;
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!map->prototype()->IsNull()) {
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    constructor = map->constructor();
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!constructor->IsNull()) {
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If the constructor is not null or a JSFunction, we have to
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // conservatively assume that it may retain a global context.
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!constructor->IsJSFunction()) return true;
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Check if the constructor directly references a foreign context.
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (CanRetainOtherContext(JSFunction::cast(constructor),
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                global_context)) {
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return true;
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    map = HeapObject::cast(map->prototype())->map();
536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  constructor = map->constructor();
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (constructor->IsNull()) return false;
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JSFunction* function = JSFunction::cast(constructor);
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return CanRetainOtherContext(function, global_context);
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function,
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               Context* global_context) {
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return function->context()->global() != global_context->global()
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      && function->context()->global() != global_context->builtins();
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void AddMapIfMissing(Handle<Map> map, SmallMapList* list) {
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < list->length(); ++i) {
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (list->at(i).is_identical_to(map)) return;
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  list->Add(map);
556592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
557592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
558592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
55969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id,
56069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                                   SmallMapList* types) {
5613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Object> object = GetInfo(ast_id);
5623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!object->IsCode()) return;
5633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<Code> code = Handle<Code>::cast(object);
5643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (code->kind() == Code::KEYED_LOAD_IC ||
5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      code->kind() == Code::KEYED_STORE_IC) {
5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    AssertNoAllocation no_allocation;
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
5683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (RelocIterator it(*code, mask); !it.done(); it.next()) {
5693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      RelocInfo* info = it.rinfo();
5703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Object* object = info->target_object();
5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (object->IsMap()) {
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Map* map = Map::cast(object);
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!CanRetainOtherContext(map, *global_context_)) {
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AddMapIfMissing(Handle<Map>(map), types);
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
58269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochbyte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) {
58369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<Object> object = GetInfo(ast_id);
58469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0;
58569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
58669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
58769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
5883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Things are a bit tricky here: The iterator for the RelocInfos and the infos
5893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// themselves are not GC-safe, so we first get all infos, then we create the
5903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// dictionary (possibly triggering GC), and finally we relocate the collected
5913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// infos before we process them.
5923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TypeFeedbackOracle::BuildDictionary(Handle<Code> code) {
5933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  AssertNoAllocation no_allocation;
5943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneList<RelocInfo> infos(16);
5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  HandleScope scope;
5963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  GetRelocInfos(code, &infos);
5973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CreateDictionary(code, &infos);
5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ProcessRelocInfos(&infos);
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ProcessTypeFeedbackCells(code);
60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Allocate handle in the parent scope.
60144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  dictionary_ = scope.CloseAndEscape(dictionary_);
602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TypeFeedbackOracle::GetRelocInfos(Handle<Code> code,
6063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                       ZoneList<RelocInfo>* infos) {
607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
6083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (RelocIterator it(*code, mask); !it.done(); it.next()) {
6093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    infos->Add(*it.rinfo());
6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
6153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                          ZoneList<RelocInfo>* infos) {
6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DisableAssertNoAllocation allocation_allowed;
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo()
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? TypeFeedbackInfo::cast(code->type_feedback_info())->
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          type_feedback_cells()->CellCount()
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : 0;
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int length = infos->length() + cell_count;
6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  byte* old_start = code->instruction_start();
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  dictionary_ = FACTORY->NewUnseededNumberDictionary(length);
6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  byte* new_start = code->instruction_start();
6253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  RelocateRelocInfos(infos, old_start, new_start);
6263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TypeFeedbackOracle::RelocateRelocInfos(ZoneList<RelocInfo>* infos,
6303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            byte* old_start,
6313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                            byte* new_start) {
6323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < infos->length(); i++) {
6333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    RelocInfo* info = &(*infos)[i];
6343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    info->set_pc(new_start + (info->pc() - old_start));
6353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
6403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < infos->length(); i++) {
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RelocInfo reloc_entry = (*infos)[i];
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address target_address = reloc_entry.target_address();
6433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    unsigned ast_id = static_cast<unsigned>((*infos)[i].data());
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Code* target = Code::GetCodeFromTargetAddress(target_address);
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (target->kind()) {
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::LOAD_IC:
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::STORE_IC:
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::CALL_IC:
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::KEYED_CALL_IC:
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (target->ic_state() == MONOMORPHIC) {
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (target->kind() == Code::CALL_IC &&
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              target->check_type() != RECEIVER_MAP_CHECK) {
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            SetInfo(ast_id, Smi::FromInt(target->check_type()));
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Object* map = target->FindFirstMap();
6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            if (map == NULL) {
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SetInfo(ast_id, static_cast<Object*>(target));
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            } else if (!CanRetainOtherContext(Map::cast(map),
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              *global_context_)) {
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SetInfo(ast_id, map);
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
66385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        } else {
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          SetInfo(ast_id, target);
66585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        }
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::KEYED_LOAD_IC:
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::KEYED_STORE_IC:
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (target->ic_state() == MONOMORPHIC ||
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            target->ic_state() == MEGAMORPHIC) {
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          SetInfo(ast_id, target);
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
675592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::UNARY_OP_IC:
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::BINARY_OP_IC:
6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::COMPARE_IC:
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Code::TO_BOOLEAN_IC:
68085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        SetInfo(ast_id, target);
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) {
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object* raw_info = code->type_feedback_info();
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!raw_info->IsTypeFeedbackInfo()) return;
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<TypeFeedbackCells> cache(
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      TypeFeedbackInfo::cast(raw_info)->type_feedback_cells());
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < cache->CellCount(); i++) {
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    unsigned ast_id = cache->AstId(i)->value();
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* value = cache->Cell(i)->value();
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (value->IsSmi() ||
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (value->IsJSFunction() &&
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         !CanRetainOtherContext(JSFunction::cast(value),
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                *global_context_))) {
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetInfo(ast_id, value);
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
7055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
7065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
7075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
7083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) {
709c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  ASSERT(dictionary_->FindEntry(ast_id) == UnseededNumberDictionary::kNotFound);
7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target);
7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  USE(maybe_result);
7123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef DEBUG
7133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Object* result = NULL;
7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Dictionary has been allocated with sufficient size for all elements.
7153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(maybe_result->ToObject(&result));
7163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(*dictionary_ == result);
7173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
7193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} }  // namespace v8::internal
721