| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 64                                        Isolate* isolate, | 64                                        Isolate* isolate, | 
| 65                                        Zone* zone) { | 65                                        Zone* zone) { | 
| 66   global_context_ = global_context; | 66   global_context_ = global_context; | 
| 67   isolate_ = isolate; | 67   isolate_ = isolate; | 
| 68   zone_ = zone; | 68   zone_ = zone; | 
| 69   BuildDictionary(code); | 69   BuildDictionary(code); | 
| 70   ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); | 70   ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); | 
| 71 } | 71 } | 
| 72 | 72 | 
| 73 | 73 | 
| 74 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { | 74 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 
| 75   int entry = dictionary_->FindEntry(ast_id); | 75   return static_cast<uint32_t>(ast_id.ToInt()); | 
|  | 76 } | 
|  | 77 | 
|  | 78 | 
|  | 79 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 
|  | 80   int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 
| 76   return entry != UnseededNumberDictionary::kNotFound | 81   return entry != UnseededNumberDictionary::kNotFound | 
| 77       ? Handle<Object>(dictionary_->ValueAt(entry)) | 82       ? Handle<Object>(dictionary_->ValueAt(entry)) | 
| 78       : Handle<Object>::cast(isolate_->factory()->undefined_value()); | 83       : Handle<Object>::cast(isolate_->factory()->undefined_value()); | 
| 79 } | 84 } | 
| 80 | 85 | 
| 81 | 86 | 
| 82 bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) { | 87 bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) { | 
| 83   Handle<Object> map_or_code = GetInfo(expr->id()); | 88   Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); | 
| 84   if (map_or_code->IsMap()) return false; | 89   if (map_or_code->IsMap()) return false; | 
| 85   if (map_or_code->IsCode()) { | 90   if (map_or_code->IsCode()) { | 
| 86     Handle<Code> code = Handle<Code>::cast(map_or_code); | 91     Handle<Code> code = Handle<Code>::cast(map_or_code); | 
| 87     return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 92     return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 
| 88   } | 93   } | 
| 89   return false; | 94   return false; | 
| 90 } | 95 } | 
| 91 | 96 | 
| 92 | 97 | 
| 93 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { | 98 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { | 
| 94   Handle<Object> map_or_code = GetInfo(expr->id()); | 99   Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); | 
| 95   if (map_or_code->IsMap()) return true; | 100   if (map_or_code->IsMap()) return true; | 
| 96   if (map_or_code->IsCode()) { | 101   if (map_or_code->IsCode()) { | 
| 97     Handle<Code> code = Handle<Code>::cast(map_or_code); | 102     Handle<Code> code = Handle<Code>::cast(map_or_code); | 
| 98     return code->is_keyed_load_stub() && | 103     return code->is_keyed_load_stub() && | 
| 99         code->ic_state() == MONOMORPHIC && | 104         code->ic_state() == MONOMORPHIC && | 
| 100         Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && | 105         Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && | 
| 101         code->FindFirstMap() != NULL && | 106         code->FindFirstMap() != NULL && | 
| 102         !CanRetainOtherContext(code->FindFirstMap(), *global_context_); | 107         !CanRetainOtherContext(code->FindFirstMap(), *global_context_); | 
| 103   } | 108   } | 
| 104   return false; | 109   return false; | 
| 105 } | 110 } | 
| 106 | 111 | 
| 107 | 112 | 
| 108 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) { | 113 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) { | 
| 109   Handle<Object> map_or_code = GetInfo(expr->id()); | 114   Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); | 
| 110   if (map_or_code->IsCode()) { | 115   if (map_or_code->IsCode()) { | 
| 111     Handle<Code> code = Handle<Code>::cast(map_or_code); | 116     Handle<Code> code = Handle<Code>::cast(map_or_code); | 
| 112     Builtins* builtins = isolate_->builtins(); | 117     Builtins* builtins = isolate_->builtins(); | 
| 113     return code->is_keyed_load_stub() && | 118     return code->is_keyed_load_stub() && | 
| 114         *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) && | 119         *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) && | 
| 115         code->ic_state() == MEGAMORPHIC; | 120         code->ic_state() == MEGAMORPHIC; | 
| 116   } | 121   } | 
| 117   return false; | 122   return false; | 
| 118 } | 123 } | 
| 119 | 124 | 
| 120 | 125 | 
| 121 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) { | 126 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(TypeFeedbackId ast_id) { | 
| 122   Handle<Object> map_or_code = GetInfo(expr->id()); | 127   Handle<Object> map_or_code = GetInfo(ast_id); | 
| 123   if (map_or_code->IsMap()) return true; | 128   if (map_or_code->IsMap()) return true; | 
| 124   if (map_or_code->IsCode()) { | 129   if (map_or_code->IsCode()) { | 
| 125     Handle<Code> code = Handle<Code>::cast(map_or_code); | 130     Handle<Code> code = Handle<Code>::cast(map_or_code); | 
| 126     bool allow_growth = | 131     bool allow_growth = | 
| 127         Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == | 132         Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == | 
| 128         ALLOW_JSARRAY_GROWTH; | 133         ALLOW_JSARRAY_GROWTH; | 
| 129     return code->is_keyed_store_stub() && | 134     return code->is_keyed_store_stub() && | 
| 130         !allow_growth && | 135         !allow_growth && | 
| 131         code->ic_state() == MONOMORPHIC && | 136         code->ic_state() == MONOMORPHIC && | 
| 132         Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && | 137         Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL && | 
| 133         code->FindFirstMap() != NULL && | 138         code->FindFirstMap() != NULL && | 
| 134         !CanRetainOtherContext(code->FindFirstMap(), *global_context_); | 139         !CanRetainOtherContext(code->FindFirstMap(), *global_context_); | 
| 135   } | 140   } | 
| 136   return false; | 141   return false; | 
| 137 } | 142 } | 
| 138 | 143 | 
| 139 | 144 | 
| 140 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(Expression* expr) { | 145 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(TypeFeedbackId ast_id) { | 
| 141   Handle<Object> map_or_code = GetInfo(expr->id()); | 146   Handle<Object> map_or_code = GetInfo(ast_id); | 
| 142   if (map_or_code->IsCode()) { | 147   if (map_or_code->IsCode()) { | 
| 143     Handle<Code> code = Handle<Code>::cast(map_or_code); | 148     Handle<Code> code = Handle<Code>::cast(map_or_code); | 
| 144     Builtins* builtins = isolate_->builtins(); | 149     Builtins* builtins = isolate_->builtins(); | 
| 145     bool allow_growth = | 150     bool allow_growth = | 
| 146         Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == | 151         Code::GetKeyedAccessGrowMode(code->extra_ic_state()) == | 
| 147         ALLOW_JSARRAY_GROWTH; | 152         ALLOW_JSARRAY_GROWTH; | 
| 148     return code->is_keyed_store_stub() && | 153     return code->is_keyed_store_stub() && | 
| 149         !allow_growth && | 154         !allow_growth && | 
| 150         *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic) && | 155         *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic) && | 
| 151         *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic_Strict) && | 156         *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic_Strict) && | 
| 152         code->ic_state() == MEGAMORPHIC; | 157         code->ic_state() == MEGAMORPHIC; | 
| 153   } | 158   } | 
| 154   return false; | 159   return false; | 
| 155 } | 160 } | 
| 156 | 161 | 
| 157 | 162 | 
| 158 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { | 163 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { | 
| 159   Handle<Object> value = GetInfo(expr->id()); | 164   Handle<Object> value = GetInfo(expr->CallFeedbackId()); | 
| 160   return value->IsMap() || value->IsSmi() || value->IsJSFunction(); | 165   return value->IsMap() || value->IsSmi() || value->IsJSFunction(); | 
| 161 } | 166 } | 
| 162 | 167 | 
| 163 | 168 | 
| 164 bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) { | 169 bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) { | 
| 165   Handle<Object> value = GetInfo(expr->id()); | 170   Handle<Object> value = GetInfo(expr->CallNewFeedbackId()); | 
| 166   return value->IsJSFunction(); | 171   return value->IsJSFunction(); | 
| 167 } | 172 } | 
| 168 | 173 | 
| 169 | 174 | 
| 170 bool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic( | 175 bool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic( | 
| 171     ObjectLiteral::Property* prop) { | 176     ObjectLiteral::Property* prop) { | 
| 172   Handle<Object> map_or_code = GetInfo(prop->key()->id()); | 177   Handle<Object> map_or_code = GetInfo(prop->key()->LiteralFeedbackId()); | 
| 173   return map_or_code->IsMap(); | 178   return map_or_code->IsMap(); | 
| 174 } | 179 } | 
| 175 | 180 | 
| 176 | 181 | 
| 177 bool TypeFeedbackOracle::IsForInFastCase(ForInStatement* stmt) { | 182 bool TypeFeedbackOracle::IsForInFastCase(ForInStatement* stmt) { | 
| 178   Handle<Object> value = GetInfo(stmt->PrepareId()); | 183   Handle<Object> value = GetInfo(stmt->ForInFeedbackId()); | 
| 179   return value->IsSmi() && | 184   return value->IsSmi() && | 
| 180       Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker; | 185       Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker; | 
| 181 } | 186 } | 
| 182 | 187 | 
| 183 | 188 | 
| 184 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { | 189 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { | 
| 185   ASSERT(LoadIsMonomorphicNormal(expr)); | 190   ASSERT(LoadIsMonomorphicNormal(expr)); | 
| 186   Handle<Object> map_or_code = GetInfo(expr->id()); | 191   Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId()); | 
| 187   if (map_or_code->IsCode()) { | 192   if (map_or_code->IsCode()) { | 
| 188     Handle<Code> code = Handle<Code>::cast(map_or_code); | 193     Handle<Code> code = Handle<Code>::cast(map_or_code); | 
| 189     Map* first_map = code->FindFirstMap(); | 194     Map* first_map = code->FindFirstMap(); | 
| 190     ASSERT(first_map != NULL); | 195     ASSERT(first_map != NULL); | 
| 191     return CanRetainOtherContext(first_map, *global_context_) | 196     return CanRetainOtherContext(first_map, *global_context_) | 
| 192         ? Handle<Map>::null() | 197         ? Handle<Map>::null() | 
| 193         : Handle<Map>(first_map); | 198         : Handle<Map>(first_map); | 
| 194   } | 199   } | 
| 195   return Handle<Map>::cast(map_or_code); | 200   return Handle<Map>::cast(map_or_code); | 
| 196 } | 201 } | 
| 197 | 202 | 
| 198 | 203 | 
| 199 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { | 204 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType( | 
| 200   ASSERT(StoreIsMonomorphicNormal(expr)); | 205     TypeFeedbackId ast_id) { | 
| 201   Handle<Object> map_or_code = GetInfo(expr->id()); | 206   ASSERT(StoreIsMonomorphicNormal(ast_id)); | 
|  | 207   Handle<Object> map_or_code = GetInfo(ast_id); | 
| 202   if (map_or_code->IsCode()) { | 208   if (map_or_code->IsCode()) { | 
| 203     Handle<Code> code = Handle<Code>::cast(map_or_code); | 209     Handle<Code> code = Handle<Code>::cast(map_or_code); | 
| 204     Map* first_map = code->FindFirstMap(); | 210     Map* first_map = code->FindFirstMap(); | 
| 205     ASSERT(first_map != NULL); | 211     ASSERT(first_map != NULL); | 
| 206     return CanRetainOtherContext(first_map, *global_context_) | 212     return CanRetainOtherContext(first_map, *global_context_) | 
| 207         ? Handle<Map>::null() | 213         ? Handle<Map>::null() | 
| 208         : Handle<Map>(first_map); | 214         : Handle<Map>(first_map); | 
| 209   } | 215   } | 
| 210   return Handle<Map>::cast(map_or_code); | 216   return Handle<Map>::cast(map_or_code); | 
| 211 } | 217 } | 
| 212 | 218 | 
| 213 | 219 | 
| 214 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr, | 220 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr, | 
| 215                                            Handle<String> name, | 221                                            Handle<String> name, | 
| 216                                            SmallMapList* types) { | 222                                            SmallMapList* types) { | 
| 217   Code::Flags flags = | 223   Code::Flags flags = | 
| 218       Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::NORMAL); | 224       Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::NORMAL); | 
| 219   CollectReceiverTypes(expr->id(), name, flags, types); | 225   CollectReceiverTypes(expr->PropertyFeedbackId(), name, flags, types); | 
| 220 } | 226 } | 
| 221 | 227 | 
| 222 | 228 | 
| 223 void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, | 229 void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, | 
| 224                                             Handle<String> name, | 230                                             Handle<String> name, | 
| 225                                             SmallMapList* types) { | 231                                             SmallMapList* types) { | 
| 226   Code::Flags flags = | 232   Code::Flags flags = | 
| 227       Code::ComputeMonomorphicFlags(Code::STORE_IC, Code::NORMAL); | 233       Code::ComputeMonomorphicFlags(Code::STORE_IC, Code::NORMAL); | 
| 228   CollectReceiverTypes(expr->id(), name, flags, types); | 234   CollectReceiverTypes(expr->AssignmentFeedbackId(), name, flags, types); | 
| 229 } | 235 } | 
| 230 | 236 | 
| 231 | 237 | 
| 232 void TypeFeedbackOracle::CallReceiverTypes(Call* expr, | 238 void TypeFeedbackOracle::CallReceiverTypes(Call* expr, | 
| 233                                            Handle<String> name, | 239                                            Handle<String> name, | 
| 234                                            CallKind call_kind, | 240                                            CallKind call_kind, | 
| 235                                            SmallMapList* types) { | 241                                            SmallMapList* types) { | 
| 236   int arity = expr->arguments()->length(); | 242   int arity = expr->arguments()->length(); | 
| 237 | 243 | 
| 238   // Note: Currently we do not take string extra ic data into account | 244   // Note: Currently we do not take string extra ic data into account | 
| 239   // here. | 245   // here. | 
| 240   Code::ExtraICState extra_ic_state = | 246   Code::ExtraICState extra_ic_state = | 
| 241       CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION); | 247       CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION); | 
| 242 | 248 | 
| 243   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 249   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 
| 244                                                     Code::NORMAL, | 250                                                     Code::NORMAL, | 
| 245                                                     extra_ic_state, | 251                                                     extra_ic_state, | 
| 246                                                     OWN_MAP, | 252                                                     OWN_MAP, | 
| 247                                                     arity); | 253                                                     arity); | 
| 248   CollectReceiverTypes(expr->id(), name, flags, types); | 254   CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types); | 
| 249 } | 255 } | 
| 250 | 256 | 
| 251 | 257 | 
| 252 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { | 258 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { | 
| 253   Handle<Object> value = GetInfo(expr->id()); | 259   Handle<Object> value = GetInfo(expr->CallFeedbackId()); | 
| 254   if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 260   if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 
| 255   CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 261   CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 
| 256   ASSERT(check != RECEIVER_MAP_CHECK); | 262   ASSERT(check != RECEIVER_MAP_CHECK); | 
| 257   return check; | 263   return check; | 
| 258 } | 264 } | 
| 259 | 265 | 
| 260 | 266 | 
| 261 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( | 267 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( | 
| 262     CheckType check) { | 268     CheckType check) { | 
| 263   JSFunction* function = NULL; | 269   JSFunction* function = NULL; | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 274     case BOOLEAN_CHECK: | 280     case BOOLEAN_CHECK: | 
| 275       function = global_context_->boolean_function(); | 281       function = global_context_->boolean_function(); | 
| 276       break; | 282       break; | 
| 277   } | 283   } | 
| 278   ASSERT(function != NULL); | 284   ASSERT(function != NULL); | 
| 279   return Handle<JSObject>(JSObject::cast(function->instance_prototype())); | 285   return Handle<JSObject>(JSObject::cast(function->instance_prototype())); | 
| 280 } | 286 } | 
| 281 | 287 | 
| 282 | 288 | 
| 283 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) { | 289 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) { | 
| 284   return Handle<JSFunction>::cast(GetInfo(expr->id())); | 290   return Handle<JSFunction>::cast(GetInfo(expr->CallFeedbackId())); | 
| 285 } | 291 } | 
| 286 | 292 | 
| 287 | 293 | 
| 288 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) { | 294 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) { | 
| 289   return Handle<JSFunction>::cast(GetInfo(expr->id())); | 295   return Handle<JSFunction>::cast(GetInfo(expr->CallNewFeedbackId())); | 
| 290 } | 296 } | 
| 291 | 297 | 
| 292 | 298 | 
| 293 Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap( | 299 Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap( | 
| 294     ObjectLiteral::Property* prop) { | 300     ObjectLiteral::Property* prop) { | 
| 295   ASSERT(ObjectLiteralStoreIsMonomorphic(prop)); | 301   ASSERT(ObjectLiteralStoreIsMonomorphic(prop)); | 
| 296   return Handle<Map>::cast(GetInfo(prop->key()->id())); | 302   return Handle<Map>::cast(GetInfo(prop->key()->LiteralFeedbackId())); | 
| 297 } | 303 } | 
| 298 | 304 | 
| 299 | 305 | 
| 300 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { | 306 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { | 
| 301   return *GetInfo(expr->id()) == | 307   return *GetInfo(expr->PropertyFeedbackId()) == | 
| 302       isolate_->builtins()->builtin(id); | 308       isolate_->builtins()->builtin(id); | 
| 303 } | 309 } | 
| 304 | 310 | 
| 305 | 311 | 
| 306 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { | 312 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { | 
| 307   Handle<Object> object = GetInfo(expr->id()); | 313   Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | 
| 308   TypeInfo unknown = TypeInfo::Unknown(); | 314   TypeInfo unknown = TypeInfo::Unknown(); | 
| 309   if (!object->IsCode()) return unknown; | 315   if (!object->IsCode()) return unknown; | 
| 310   Handle<Code> code = Handle<Code>::cast(object); | 316   Handle<Code> code = Handle<Code>::cast(object); | 
| 311   if (!code->is_compare_ic_stub()) return unknown; | 317   if (!code->is_compare_ic_stub()) return unknown; | 
| 312 | 318 | 
| 313   CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 319   CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 
| 314   switch (state) { | 320   switch (state) { | 
| 315     case CompareIC::UNINITIALIZED: | 321     case CompareIC::UNINITIALIZED: | 
| 316       // Uninitialized means never executed. | 322       // Uninitialized means never executed. | 
| 317       return TypeInfo::Uninitialized(); | 323       return TypeInfo::Uninitialized(); | 
| 318     case CompareIC::SMIS: | 324     case CompareIC::SMIS: | 
| 319       return TypeInfo::Smi(); | 325       return TypeInfo::Smi(); | 
| 320     case CompareIC::HEAP_NUMBERS: | 326     case CompareIC::HEAP_NUMBERS: | 
| 321       return TypeInfo::Number(); | 327       return TypeInfo::Number(); | 
| 322     case CompareIC::SYMBOLS: | 328     case CompareIC::SYMBOLS: | 
| 323     case CompareIC::STRINGS: | 329     case CompareIC::STRINGS: | 
| 324       return TypeInfo::String(); | 330       return TypeInfo::String(); | 
| 325     case CompareIC::OBJECTS: | 331     case CompareIC::OBJECTS: | 
| 326     case CompareIC::KNOWN_OBJECTS: | 332     case CompareIC::KNOWN_OBJECTS: | 
| 327       // TODO(kasperl): We really need a type for JS objects here. | 333       // TODO(kasperl): We really need a type for JS objects here. | 
| 328       return TypeInfo::NonPrimitive(); | 334       return TypeInfo::NonPrimitive(); | 
| 329     case CompareIC::GENERIC: | 335     case CompareIC::GENERIC: | 
| 330     default: | 336     default: | 
| 331       return unknown; | 337       return unknown; | 
| 332   } | 338   } | 
| 333 } | 339 } | 
| 334 | 340 | 
| 335 | 341 | 
| 336 bool TypeFeedbackOracle::IsSymbolCompare(CompareOperation* expr) { | 342 bool TypeFeedbackOracle::IsSymbolCompare(CompareOperation* expr) { | 
| 337   Handle<Object> object = GetInfo(expr->id()); | 343   Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | 
| 338   if (!object->IsCode()) return false; | 344   if (!object->IsCode()) return false; | 
| 339   Handle<Code> code = Handle<Code>::cast(object); | 345   Handle<Code> code = Handle<Code>::cast(object); | 
| 340   if (!code->is_compare_ic_stub()) return false; | 346   if (!code->is_compare_ic_stub()) return false; | 
| 341   CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 347   CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 
| 342   return state == CompareIC::SYMBOLS; | 348   return state == CompareIC::SYMBOLS; | 
| 343 } | 349 } | 
| 344 | 350 | 
| 345 | 351 | 
| 346 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { | 352 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { | 
| 347   Handle<Object> object = GetInfo(expr->id()); | 353   Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); | 
| 348   if (!object->IsCode()) return Handle<Map>::null(); | 354   if (!object->IsCode()) return Handle<Map>::null(); | 
| 349   Handle<Code> code = Handle<Code>::cast(object); | 355   Handle<Code> code = Handle<Code>::cast(object); | 
| 350   if (!code->is_compare_ic_stub()) return Handle<Map>::null(); | 356   if (!code->is_compare_ic_stub()) return Handle<Map>::null(); | 
| 351   CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 357   CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 
| 352   if (state != CompareIC::KNOWN_OBJECTS) { | 358   if (state != CompareIC::KNOWN_OBJECTS) { | 
| 353     return Handle<Map>::null(); | 359     return Handle<Map>::null(); | 
| 354   } | 360   } | 
| 355   Map* first_map = code->FindFirstMap(); | 361   Map* first_map = code->FindFirstMap(); | 
| 356   ASSERT(first_map != NULL); | 362   ASSERT(first_map != NULL); | 
| 357   return CanRetainOtherContext(first_map, *global_context_) | 363   return CanRetainOtherContext(first_map, *global_context_) | 
| 358       ? Handle<Map>::null() | 364       ? Handle<Map>::null() | 
| 359       : Handle<Map>(first_map); | 365       : Handle<Map>(first_map); | 
| 360 } | 366 } | 
| 361 | 367 | 
| 362 | 368 | 
| 363 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { | 369 TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) { | 
| 364   Handle<Object> object = GetInfo(expr->id()); | 370   Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId()); | 
| 365   TypeInfo unknown = TypeInfo::Unknown(); | 371   TypeInfo unknown = TypeInfo::Unknown(); | 
| 366   if (!object->IsCode()) return unknown; | 372   if (!object->IsCode()) return unknown; | 
| 367   Handle<Code> code = Handle<Code>::cast(object); | 373   Handle<Code> code = Handle<Code>::cast(object); | 
| 368   ASSERT(code->is_unary_op_stub()); | 374   ASSERT(code->is_unary_op_stub()); | 
| 369   UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( | 375   UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>( | 
| 370       code->unary_op_type()); | 376       code->unary_op_type()); | 
| 371   switch (type) { | 377   switch (type) { | 
| 372     case UnaryOpIC::SMI: | 378     case UnaryOpIC::SMI: | 
| 373       return TypeInfo::Smi(); | 379       return TypeInfo::Smi(); | 
| 374     case UnaryOpIC::HEAP_NUMBER: | 380     case UnaryOpIC::HEAP_NUMBER: | 
| 375       return TypeInfo::Double(); | 381       return TypeInfo::Double(); | 
| 376     default: | 382     default: | 
| 377       return unknown; | 383       return unknown; | 
| 378   } | 384   } | 
| 379 } | 385 } | 
| 380 | 386 | 
| 381 | 387 | 
| 382 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { | 388 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { | 
| 383   Handle<Object> object = GetInfo(expr->id()); | 389   Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId()); | 
| 384   TypeInfo unknown = TypeInfo::Unknown(); | 390   TypeInfo unknown = TypeInfo::Unknown(); | 
| 385   if (!object->IsCode()) return unknown; | 391   if (!object->IsCode()) return unknown; | 
| 386   Handle<Code> code = Handle<Code>::cast(object); | 392   Handle<Code> code = Handle<Code>::cast(object); | 
| 387   if (code->is_binary_op_stub()) { | 393   if (code->is_binary_op_stub()) { | 
| 388     BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( | 394     BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( | 
| 389         code->binary_op_type()); | 395         code->binary_op_type()); | 
| 390     BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>( | 396     BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>( | 
| 391         code->binary_op_result_type()); | 397         code->binary_op_result_type()); | 
| 392 | 398 | 
| 393     switch (type) { | 399     switch (type) { | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 457       // TODO(kasperl): We really need a type for JS objects here. | 463       // TODO(kasperl): We really need a type for JS objects here. | 
| 458       return TypeInfo::NonPrimitive(); | 464       return TypeInfo::NonPrimitive(); | 
| 459     case CompareIC::GENERIC: | 465     case CompareIC::GENERIC: | 
| 460     default: | 466     default: | 
| 461       return unknown; | 467       return unknown; | 
| 462   } | 468   } | 
| 463 } | 469 } | 
| 464 | 470 | 
| 465 | 471 | 
| 466 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { | 472 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { | 
| 467   Handle<Object> object = GetInfo(expr->CountId()); | 473   Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); | 
| 468   TypeInfo unknown = TypeInfo::Unknown(); | 474   TypeInfo unknown = TypeInfo::Unknown(); | 
| 469   if (!object->IsCode()) return unknown; | 475   if (!object->IsCode()) return unknown; | 
| 470   Handle<Code> code = Handle<Code>::cast(object); | 476   Handle<Code> code = Handle<Code>::cast(object); | 
| 471   if (!code->is_binary_op_stub()) return unknown; | 477   if (!code->is_binary_op_stub()) return unknown; | 
| 472 | 478 | 
| 473   BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( | 479   BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( | 
| 474       code->binary_op_type()); | 480       code->binary_op_type()); | 
| 475   switch (type) { | 481   switch (type) { | 
| 476     case BinaryOpIC::UNINITIALIZED: | 482     case BinaryOpIC::UNINITIALIZED: | 
| 477     case BinaryOpIC::SMI: | 483     case BinaryOpIC::SMI: | 
| 478       return TypeInfo::Smi(); | 484       return TypeInfo::Smi(); | 
| 479     case BinaryOpIC::INT32: | 485     case BinaryOpIC::INT32: | 
| 480       return TypeInfo::Integer32(); | 486       return TypeInfo::Integer32(); | 
| 481     case BinaryOpIC::HEAP_NUMBER: | 487     case BinaryOpIC::HEAP_NUMBER: | 
| 482       return TypeInfo::Double(); | 488       return TypeInfo::Double(); | 
| 483     case BinaryOpIC::BOTH_STRING: | 489     case BinaryOpIC::BOTH_STRING: | 
| 484     case BinaryOpIC::STRING: | 490     case BinaryOpIC::STRING: | 
| 485     case BinaryOpIC::GENERIC: | 491     case BinaryOpIC::GENERIC: | 
| 486       return unknown; | 492       return unknown; | 
| 487     default: | 493     default: | 
| 488       return unknown; | 494       return unknown; | 
| 489   } | 495   } | 
| 490   UNREACHABLE(); | 496   UNREACHABLE(); | 
| 491   return unknown; | 497   return unknown; | 
| 492 } | 498 } | 
| 493 | 499 | 
| 494 | 500 | 
| 495 void TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, | 501 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, | 
| 496                                               Handle<String> name, | 502                                               Handle<String> name, | 
| 497                                               Code::Flags flags, | 503                                               Code::Flags flags, | 
| 498                                               SmallMapList* types) { | 504                                               SmallMapList* types) { | 
| 499   Handle<Object> object = GetInfo(ast_id); | 505   Handle<Object> object = GetInfo(ast_id); | 
| 500   if (object->IsUndefined() || object->IsSmi()) return; | 506   if (object->IsUndefined() || object->IsSmi()) return; | 
| 501 | 507 | 
| 502   if (*object == | 508   if (*object == | 
| 503       isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 509       isolate_->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 
| 504     // TODO(fschneider): We could collect the maps and signal that | 510     // TODO(fschneider): We could collect the maps and signal that | 
| 505     // we need a generic store (or load) here. | 511     // we need a generic store (or load) here. | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 555 | 561 | 
| 556 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list, | 562 static void AddMapIfMissing(Handle<Map> map, SmallMapList* list, | 
| 557                             Zone* zone) { | 563                             Zone* zone) { | 
| 558   for (int i = 0; i < list->length(); ++i) { | 564   for (int i = 0; i < list->length(); ++i) { | 
| 559     if (list->at(i).is_identical_to(map)) return; | 565     if (list->at(i).is_identical_to(map)) return; | 
| 560   } | 566   } | 
| 561   list->Add(map, zone); | 567   list->Add(map, zone); | 
| 562 } | 568 } | 
| 563 | 569 | 
| 564 | 570 | 
| 565 void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id, | 571 void TypeFeedbackOracle::CollectKeyedReceiverTypes(TypeFeedbackId ast_id, | 
| 566                                                    SmallMapList* types) { | 572                                                    SmallMapList* types) { | 
| 567   Handle<Object> object = GetInfo(ast_id); | 573   Handle<Object> object = GetInfo(ast_id); | 
| 568   if (!object->IsCode()) return; | 574   if (!object->IsCode()) return; | 
| 569   Handle<Code> code = Handle<Code>::cast(object); | 575   Handle<Code> code = Handle<Code>::cast(object); | 
| 570   if (code->kind() == Code::KEYED_LOAD_IC || | 576   if (code->kind() == Code::KEYED_LOAD_IC || | 
| 571       code->kind() == Code::KEYED_STORE_IC) { | 577       code->kind() == Code::KEYED_STORE_IC) { | 
| 572     AssertNoAllocation no_allocation; | 578     AssertNoAllocation no_allocation; | 
| 573     int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 579     int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 
| 574     for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 580     for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 
| 575       RelocInfo* info = it.rinfo(); | 581       RelocInfo* info = it.rinfo(); | 
| 576       Object* object = info->target_object(); | 582       Object* object = info->target_object(); | 
| 577       if (object->IsMap()) { | 583       if (object->IsMap()) { | 
| 578         Map* map = Map::cast(object); | 584         Map* map = Map::cast(object); | 
| 579         if (!CanRetainOtherContext(map, *global_context_)) { | 585         if (!CanRetainOtherContext(map, *global_context_)) { | 
| 580           AddMapIfMissing(Handle<Map>(map), types, zone()); | 586           AddMapIfMissing(Handle<Map>(map), types, zone()); | 
| 581         } | 587         } | 
| 582       } | 588       } | 
| 583     } | 589     } | 
| 584   } | 590   } | 
| 585 } | 591 } | 
| 586 | 592 | 
| 587 | 593 | 
| 588 byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) { | 594 byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId ast_id) { | 
| 589   Handle<Object> object = GetInfo(ast_id); | 595   Handle<Object> object = GetInfo(ast_id); | 
| 590   return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 596   return object->IsCode() ? Handle<Code>::cast(object)->to_boolean_state() : 0; | 
| 591 } | 597 } | 
| 592 | 598 | 
| 593 | 599 | 
| 594 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 600 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 
| 595 // themselves are not GC-safe, so we first get all infos, then we create the | 601 // themselves are not GC-safe, so we first get all infos, then we create the | 
| 596 // dictionary (possibly triggering GC), and finally we relocate the collected | 602 // dictionary (possibly triggering GC), and finally we relocate the collected | 
| 597 // infos before we process them. | 603 // infos before we process them. | 
| 598 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 604 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 639     RelocInfo* info = &(*infos)[i]; | 645     RelocInfo* info = &(*infos)[i]; | 
| 640     info->set_pc(new_start + (info->pc() - old_start)); | 646     info->set_pc(new_start + (info->pc() - old_start)); | 
| 641   } | 647   } | 
| 642 } | 648 } | 
| 643 | 649 | 
| 644 | 650 | 
| 645 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { | 651 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { | 
| 646   for (int i = 0; i < infos->length(); i++) { | 652   for (int i = 0; i < infos->length(); i++) { | 
| 647     RelocInfo reloc_entry = (*infos)[i]; | 653     RelocInfo reloc_entry = (*infos)[i]; | 
| 648     Address target_address = reloc_entry.target_address(); | 654     Address target_address = reloc_entry.target_address(); | 
| 649     unsigned ast_id = static_cast<unsigned>((*infos)[i].data()); | 655     TypeFeedbackId ast_id = | 
|  | 656         TypeFeedbackId(static_cast<unsigned>((*infos)[i].data())); | 
| 650     Code* target = Code::GetCodeFromTargetAddress(target_address); | 657     Code* target = Code::GetCodeFromTargetAddress(target_address); | 
| 651     switch (target->kind()) { | 658     switch (target->kind()) { | 
| 652       case Code::LOAD_IC: | 659       case Code::LOAD_IC: | 
| 653       case Code::STORE_IC: | 660       case Code::STORE_IC: | 
| 654       case Code::CALL_IC: | 661       case Code::CALL_IC: | 
| 655       case Code::KEYED_CALL_IC: | 662       case Code::KEYED_CALL_IC: | 
| 656         if (target->ic_state() == MONOMORPHIC) { | 663         if (target->ic_state() == MONOMORPHIC) { | 
| 657           if (target->kind() == Code::CALL_IC && | 664           if (target->kind() == Code::CALL_IC && | 
| 658               target->check_type() != RECEIVER_MAP_CHECK) { | 665               target->check_type() != RECEIVER_MAP_CHECK) { | 
| 659             SetInfo(ast_id, Smi::FromInt(target->check_type())); | 666             SetInfo(ast_id, Smi::FromInt(target->check_type())); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 692   } | 699   } | 
| 693 } | 700 } | 
| 694 | 701 | 
| 695 | 702 | 
| 696 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { | 703 void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { | 
| 697   Object* raw_info = code->type_feedback_info(); | 704   Object* raw_info = code->type_feedback_info(); | 
| 698   if (!raw_info->IsTypeFeedbackInfo()) return; | 705   if (!raw_info->IsTypeFeedbackInfo()) return; | 
| 699   Handle<TypeFeedbackCells> cache( | 706   Handle<TypeFeedbackCells> cache( | 
| 700       TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); | 707       TypeFeedbackInfo::cast(raw_info)->type_feedback_cells()); | 
| 701   for (int i = 0; i < cache->CellCount(); i++) { | 708   for (int i = 0; i < cache->CellCount(); i++) { | 
| 702     unsigned ast_id = cache->AstId(i)->value(); | 709     TypeFeedbackId ast_id = cache->AstId(i); | 
| 703     Object* value = cache->Cell(i)->value(); | 710     Object* value = cache->Cell(i)->value(); | 
| 704     if (value->IsSmi() || | 711     if (value->IsSmi() || | 
| 705         (value->IsJSFunction() && | 712         (value->IsJSFunction() && | 
| 706          !CanRetainOtherContext(JSFunction::cast(value), | 713          !CanRetainOtherContext(JSFunction::cast(value), | 
| 707                                 *global_context_))) { | 714                                 *global_context_))) { | 
| 708       SetInfo(ast_id, value); | 715       SetInfo(ast_id, value); | 
| 709     } | 716     } | 
| 710   } | 717   } | 
| 711 } | 718 } | 
| 712 | 719 | 
| 713 | 720 | 
| 714 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { | 721 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { | 
| 715   ASSERT(dictionary_->FindEntry(ast_id) == UnseededNumberDictionary::kNotFound); | 722   ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == | 
| 716   MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); | 723          UnseededNumberDictionary::kNotFound); | 
|  | 724   MaybeObject* maybe_result = dictionary_->AtNumberPut(IdToKey(ast_id), target); | 
| 717   USE(maybe_result); | 725   USE(maybe_result); | 
| 718 #ifdef DEBUG | 726 #ifdef DEBUG | 
| 719   Object* result = NULL; | 727   Object* result = NULL; | 
| 720   // Dictionary has been allocated with sufficient size for all elements. | 728   // Dictionary has been allocated with sufficient size for all elements. | 
| 721   ASSERT(maybe_result->ToObject(&result)); | 729   ASSERT(maybe_result->ToObject(&result)); | 
| 722   ASSERT(*dictionary_ == result); | 730   ASSERT(*dictionary_ == result); | 
| 723 #endif | 731 #endif | 
| 724 } | 732 } | 
| 725 | 733 | 
| 726 } }  // namespace v8::internal | 734 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|