| 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 |