| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 | 62 |
| 63 | 63 |
| 64 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 64 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
| 65 Handle<Context> global_context) { | 65 Handle<Context> global_context) { |
| 66 global_context_ = global_context; | 66 global_context_ = global_context; |
| 67 PopulateMap(code); | 67 PopulateMap(code); |
| 68 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); | 68 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); |
| 69 } | 69 } |
| 70 | 70 |
| 71 | 71 |
| 72 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { | 72 Handle<Object> TypeFeedbackOracle::GetInfo(int pos) { |
| 73 int entry = dictionary_->FindEntry(ast_id); | 73 int entry = dictionary_->FindEntry(pos); |
| 74 return entry != NumberDictionary::kNotFound | 74 return entry != NumberDictionary::kNotFound |
| 75 ? Handle<Object>(dictionary_->ValueAt(entry)) | 75 ? Handle<Object>(dictionary_->ValueAt(entry)) |
| 76 : Isolate::Current()->factory()->undefined_value(); | 76 : Isolate::Current()->factory()->undefined_value(); |
| 77 } | 77 } |
| 78 | 78 |
| 79 | 79 |
| 80 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) { | 80 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) { |
| 81 Handle<Object> map_or_code(GetInfo(expr->id())); | 81 Handle<Object> map_or_code(GetInfo(expr->position())); |
| 82 if (map_or_code->IsMap()) return true; | 82 if (map_or_code->IsMap()) return true; |
| 83 if (map_or_code->IsCode()) { | 83 if (map_or_code->IsCode()) { |
| 84 Handle<Code> code(Code::cast(*map_or_code)); | 84 Handle<Code> code(Code::cast(*map_or_code)); |
| 85 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC && | 85 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC && |
| 86 code->FindFirstMap() != NULL; | 86 code->FindFirstMap() != NULL; |
| 87 } | 87 } |
| 88 return false; | 88 return false; |
| 89 } | 89 } |
| 90 | 90 |
| 91 | 91 |
| 92 bool TypeFeedbackOracle::StoreIsMonomorphic(Expression* expr) { | 92 bool TypeFeedbackOracle::StoreIsMonomorphic(Expression* expr) { |
| 93 Handle<Object> map_or_code(GetInfo(expr->id())); | 93 Handle<Object> map_or_code(GetInfo(expr->position())); |
| 94 if (map_or_code->IsMap()) return true; | 94 if (map_or_code->IsMap()) return true; |
| 95 if (map_or_code->IsCode()) { | 95 if (map_or_code->IsCode()) { |
| 96 Handle<Code> code(Code::cast(*map_or_code)); | 96 Handle<Code> code(Code::cast(*map_or_code)); |
| 97 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_STORE_IC && | 97 return code->kind() == Code::KEYED_EXTERNAL_ARRAY_STORE_IC && |
| 98 code->FindFirstMap() != NULL; | 98 code->FindFirstMap() != NULL; |
| 99 } | 99 } |
| 100 return false; | 100 return false; |
| 101 } | 101 } |
| 102 | 102 |
| 103 | 103 |
| 104 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { | 104 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { |
| 105 Handle<Object> value = GetInfo(expr->id()); | 105 Handle<Object> value = GetInfo(expr->position()); |
| 106 return value->IsMap() || value->IsSmi(); | 106 return value->IsMap() || value->IsSmi(); |
| 107 } | 107 } |
| 108 | 108 |
| 109 | 109 |
| 110 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { | 110 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { |
| 111 ASSERT(LoadIsMonomorphic(expr)); | 111 ASSERT(LoadIsMonomorphic(expr)); |
| 112 Handle<Object> map_or_code( | 112 Handle<Object> map_or_code( |
| 113 Handle<HeapObject>::cast(GetInfo(expr->id()))); | 113 Handle<HeapObject>::cast(GetInfo(expr->position()))); |
| 114 if (map_or_code->IsCode()) { | 114 if (map_or_code->IsCode()) { |
| 115 Handle<Code> code(Code::cast(*map_or_code)); | 115 Handle<Code> code(Code::cast(*map_or_code)); |
| 116 return Handle<Map>(code->FindFirstMap()); | 116 return Handle<Map>(code->FindFirstMap()); |
| 117 } | 117 } |
| 118 return Handle<Map>(Map::cast(*map_or_code)); | 118 return Handle<Map>(Map::cast(*map_or_code)); |
| 119 } | 119 } |
| 120 | 120 |
| 121 | 121 |
| 122 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { | 122 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { |
| 123 ASSERT(StoreIsMonomorphic(expr)); | 123 ASSERT(StoreIsMonomorphic(expr)); |
| 124 Handle<HeapObject> map_or_code( | 124 Handle<HeapObject> map_or_code( |
| 125 Handle<HeapObject>::cast(GetInfo(expr->id()))); | 125 Handle<HeapObject>::cast(GetInfo(expr->position()))); |
| 126 if (map_or_code->IsCode()) { | 126 if (map_or_code->IsCode()) { |
| 127 Handle<Code> code(Code::cast(*map_or_code)); | 127 Handle<Code> code(Code::cast(*map_or_code)); |
| 128 return Handle<Map>(code->FindFirstMap()); | 128 return Handle<Map>(code->FindFirstMap()); |
| 129 } | 129 } |
| 130 return Handle<Map>(Map::cast(*map_or_code)); | 130 return Handle<Map>(Map::cast(*map_or_code)); |
| 131 } | 131 } |
| 132 | 132 |
| 133 | 133 |
| 134 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, | 134 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, |
| 135 Handle<String> name) { | 135 Handle<String> name) { |
| 136 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); | 136 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); |
| 137 return CollectReceiverTypes(expr->id(), name, flags); | 137 return CollectReceiverTypes(expr->position(), name, flags); |
| 138 } | 138 } |
| 139 | 139 |
| 140 | 140 |
| 141 ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, | 141 ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr, |
| 142 Handle<String> name) { | 142 Handle<String> name) { |
| 143 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); | 143 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); |
| 144 return CollectReceiverTypes(expr->id(), name, flags); | 144 return CollectReceiverTypes(expr->position(), name, flags); |
| 145 } | 145 } |
| 146 | 146 |
| 147 | 147 |
| 148 ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr, | 148 ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr, |
| 149 Handle<String> name) { | 149 Handle<String> name) { |
| 150 int arity = expr->arguments()->length(); | 150 int arity = expr->arguments()->length(); |
| 151 // Note: these flags won't let us get maps from stubs with | 151 // Note: these flags won't let us get maps from stubs with |
| 152 // non-default extra ic state in the megamorphic case. In the more | 152 // non-default extra ic state in the megamorphic case. In the more |
| 153 // important monomorphic case the map is obtained directly, so it's | 153 // important monomorphic case the map is obtained directly, so it's |
| 154 // not a problem until we decide to emit more polymorphic code. | 154 // not a problem until we decide to emit more polymorphic code. |
| 155 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, | 155 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, |
| 156 NORMAL, | 156 NORMAL, |
| 157 Code::kNoExtraICState, | 157 Code::kNoExtraICState, |
| 158 OWN_MAP, | 158 OWN_MAP, |
| 159 NOT_IN_LOOP, | 159 NOT_IN_LOOP, |
| 160 arity); | 160 arity); |
| 161 return CollectReceiverTypes(expr->id(), name, flags); | 161 return CollectReceiverTypes(expr->position(), name, flags); |
| 162 } | 162 } |
| 163 | 163 |
| 164 | 164 |
| 165 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { | 165 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { |
| 166 Handle<Object> value = GetInfo(expr->id()); | 166 Handle<Object> value = GetInfo(expr->position()); |
| 167 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 167 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; |
| 168 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 168 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); |
| 169 ASSERT(check != RECEIVER_MAP_CHECK); | 169 ASSERT(check != RECEIVER_MAP_CHECK); |
| 170 return check; | 170 return check; |
| 171 } | 171 } |
| 172 | 172 |
| 173 ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType( | 173 ExternalArrayType TypeFeedbackOracle::GetKeyedLoadExternalArrayType( |
| 174 Property* expr) { | 174 Property* expr) { |
| 175 Handle<Object> stub = GetInfo(expr->id()); | 175 Handle<Object> stub = GetInfo(expr->position()); |
| 176 ASSERT(stub->IsCode()); | 176 ASSERT(stub->IsCode()); |
| 177 return Code::cast(*stub)->external_array_type(); | 177 return Code::cast(*stub)->external_array_type(); |
| 178 } | 178 } |
| 179 | 179 |
| 180 ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType( | 180 ExternalArrayType TypeFeedbackOracle::GetKeyedStoreExternalArrayType( |
| 181 Expression* expr) { | 181 Expression* expr) { |
| 182 Handle<Object> stub = GetInfo(expr->id()); | 182 Handle<Object> stub = GetInfo(expr->position()); |
| 183 ASSERT(stub->IsCode()); | 183 ASSERT(stub->IsCode()); |
| 184 return Code::cast(*stub)->external_array_type(); | 184 return Code::cast(*stub)->external_array_type(); |
| 185 } | 185 } |
| 186 | 186 |
| 187 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( | 187 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( |
| 188 CheckType check) { | 188 CheckType check) { |
| 189 JSFunction* function = NULL; | 189 JSFunction* function = NULL; |
| 190 switch (check) { | 190 switch (check) { |
| 191 case RECEIVER_MAP_CHECK: | 191 case RECEIVER_MAP_CHECK: |
| 192 UNREACHABLE(); | 192 UNREACHABLE(); |
| 193 break; | 193 break; |
| 194 case STRING_CHECK: | 194 case STRING_CHECK: |
| 195 function = global_context_->string_function(); | 195 function = global_context_->string_function(); |
| 196 break; | 196 break; |
| 197 case NUMBER_CHECK: | 197 case NUMBER_CHECK: |
| 198 function = global_context_->number_function(); | 198 function = global_context_->number_function(); |
| 199 break; | 199 break; |
| 200 case BOOLEAN_CHECK: | 200 case BOOLEAN_CHECK: |
| 201 function = global_context_->boolean_function(); | 201 function = global_context_->boolean_function(); |
| 202 break; | 202 break; |
| 203 } | 203 } |
| 204 ASSERT(function != NULL); | 204 ASSERT(function != NULL); |
| 205 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); | 205 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); |
| 206 } | 206 } |
| 207 | 207 |
| 208 | 208 |
| 209 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { | 209 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { |
| 210 return *GetInfo(expr->id()) == | 210 return *GetInfo(expr->position()) == |
| 211 Isolate::Current()->builtins()->builtin(id); | 211 Isolate::Current()->builtins()->builtin(id); |
| 212 } | 212 } |
| 213 | 213 |
| 214 | 214 |
| 215 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { | 215 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { |
| 216 Handle<Object> object = GetInfo(expr->id()); | 216 Handle<Object> object = GetInfo(expr->position()); |
| 217 TypeInfo unknown = TypeInfo::Unknown(); | 217 TypeInfo unknown = TypeInfo::Unknown(); |
| 218 if (!object->IsCode()) return unknown; | 218 if (!object->IsCode()) return unknown; |
| 219 Handle<Code> code = Handle<Code>::cast(object); | 219 Handle<Code> code = Handle<Code>::cast(object); |
| 220 if (!code->is_compare_ic_stub()) return unknown; | 220 if (!code->is_compare_ic_stub()) return unknown; |
| 221 | 221 |
| 222 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 222 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
| 223 switch (state) { | 223 switch (state) { |
| 224 case CompareIC::UNINITIALIZED: | 224 case CompareIC::UNINITIALIZED: |
| 225 // Uninitialized means never executed. | 225 // Uninitialized means never executed. |
| 226 // TODO(fschneider): Introduce a separate value for never-executed ICs. | 226 // TODO(fschneider): Introduce a separate value for never-executed ICs. |
| 227 return unknown; | 227 return unknown; |
| 228 case CompareIC::SMIS: | 228 case CompareIC::SMIS: |
| 229 return TypeInfo::Smi(); | 229 return TypeInfo::Smi(); |
| 230 case CompareIC::HEAP_NUMBERS: | 230 case CompareIC::HEAP_NUMBERS: |
| 231 return TypeInfo::Number(); | 231 return TypeInfo::Number(); |
| 232 case CompareIC::OBJECTS: | 232 case CompareIC::OBJECTS: |
| 233 // TODO(kasperl): We really need a type for JS objects here. | 233 // TODO(kasperl): We really need a type for JS objects here. |
| 234 return TypeInfo::NonPrimitive(); | 234 return TypeInfo::NonPrimitive(); |
| 235 case CompareIC::GENERIC: | 235 case CompareIC::GENERIC: |
| 236 default: | 236 default: |
| 237 return unknown; | 237 return unknown; |
| 238 } | 238 } |
| 239 } | 239 } |
| 240 | 240 |
| 241 | 241 |
| 242 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { | 242 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { |
| 243 Handle<Object> object = GetInfo(expr->id()); | 243 Handle<Object> object = GetInfo(expr->position()); |
| 244 TypeInfo unknown = TypeInfo::Unknown(); | 244 TypeInfo unknown = TypeInfo::Unknown(); |
| 245 if (!object->IsCode()) return unknown; | 245 if (!object->IsCode()) return unknown; |
| 246 Handle<Code> code = Handle<Code>::cast(object); | 246 Handle<Code> code = Handle<Code>::cast(object); |
| 247 if (code->is_type_recording_binary_op_stub()) { | 247 if (code->is_type_recording_binary_op_stub()) { |
| 248 TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>( | 248 TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>( |
| 249 code->type_recording_binary_op_type()); | 249 code->type_recording_binary_op_type()); |
| 250 TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>( | 250 TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>( |
| 251 code->type_recording_binary_op_result_type()); | 251 code->type_recording_binary_op_result_type()); |
| 252 | 252 |
| 253 switch (type) { | 253 switch (type) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 282 return unknown; | 282 return unknown; |
| 283 default: | 283 default: |
| 284 return unknown; | 284 return unknown; |
| 285 } | 285 } |
| 286 } | 286 } |
| 287 return unknown; | 287 return unknown; |
| 288 } | 288 } |
| 289 | 289 |
| 290 | 290 |
| 291 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { | 291 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { |
| 292 Handle<Object> object = GetInfo(clause->label()->id()); | 292 Handle<Object> object = GetInfo(clause->position()); |
| 293 TypeInfo unknown = TypeInfo::Unknown(); | 293 TypeInfo unknown = TypeInfo::Unknown(); |
| 294 if (!object->IsCode()) return unknown; | 294 if (!object->IsCode()) return unknown; |
| 295 Handle<Code> code = Handle<Code>::cast(object); | 295 Handle<Code> code = Handle<Code>::cast(object); |
| 296 if (!code->is_compare_ic_stub()) return unknown; | 296 if (!code->is_compare_ic_stub()) return unknown; |
| 297 | 297 |
| 298 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 298 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
| 299 switch (state) { | 299 switch (state) { |
| 300 case CompareIC::UNINITIALIZED: | 300 case CompareIC::UNINITIALIZED: |
| 301 // Uninitialized means never executed. | 301 // Uninitialized means never executed. |
| 302 // TODO(fschneider): Introduce a separate value for never-executed ICs. | 302 // TODO(fschneider): Introduce a separate value for never-executed ICs. |
| 303 return unknown; | 303 return unknown; |
| 304 case CompareIC::SMIS: | 304 case CompareIC::SMIS: |
| 305 return TypeInfo::Smi(); | 305 return TypeInfo::Smi(); |
| 306 case CompareIC::HEAP_NUMBERS: | 306 case CompareIC::HEAP_NUMBERS: |
| 307 return TypeInfo::Number(); | 307 return TypeInfo::Number(); |
| 308 case CompareIC::OBJECTS: | 308 case CompareIC::OBJECTS: |
| 309 // TODO(kasperl): We really need a type for JS objects here. | 309 // TODO(kasperl): We really need a type for JS objects here. |
| 310 return TypeInfo::NonPrimitive(); | 310 return TypeInfo::NonPrimitive(); |
| 311 case CompareIC::GENERIC: | 311 case CompareIC::GENERIC: |
| 312 default: | 312 default: |
| 313 return unknown; | 313 return unknown; |
| 314 } | 314 } |
| 315 } | 315 } |
| 316 | 316 |
| 317 | 317 |
| 318 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, | 318 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, |
| 319 Handle<String> name, | 319 Handle<String> name, |
| 320 Code::Flags flags) { | 320 Code::Flags flags) { |
| 321 Isolate* isolate = Isolate::Current(); | 321 Isolate* isolate = Isolate::Current(); |
| 322 Handle<Object> object = GetInfo(ast_id); | 322 Handle<Object> object = GetInfo(position); |
| 323 if (object->IsUndefined() || object->IsSmi()) return NULL; | 323 if (object->IsUndefined() || object->IsSmi()) return NULL; |
| 324 | 324 |
| 325 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 325 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { |
| 326 // TODO(fschneider): We could collect the maps and signal that | 326 // TODO(fschneider): We could collect the maps and signal that |
| 327 // we need a generic store (or load) here. | 327 // we need a generic store (or load) here. |
| 328 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); | 328 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); |
| 329 return NULL; | 329 return NULL; |
| 330 } else if (object->IsMap()) { | 330 } else if (object->IsMap()) { |
| 331 ZoneMapList* types = new ZoneMapList(1); | 331 ZoneMapList* types = new ZoneMapList(1); |
| 332 types->Add(Handle<Map>::cast(object)); | 332 types->Add(Handle<Map>::cast(object)); |
| 333 return types; | 333 return types; |
| 334 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { | 334 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { |
| 335 ZoneMapList* types = new ZoneMapList(4); | 335 ZoneMapList* types = new ZoneMapList(4); |
| 336 ASSERT(object->IsCode()); | 336 ASSERT(object->IsCode()); |
| 337 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); | 337 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); |
| 338 return types->length() > 0 ? types : NULL; | 338 return types->length() > 0 ? types : NULL; |
| 339 } else { | 339 } else { |
| 340 return NULL; | 340 return NULL; |
| 341 } | 341 } |
| 342 } | 342 } |
| 343 | 343 |
| 344 | 344 |
| 345 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { | 345 void TypeFeedbackOracle::SetInfo(int position, Object* target) { |
| 346 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound); | 346 MaybeObject* maybe_result = dictionary_->AtNumberPut(position, target); |
| 347 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); | |
| 348 USE(maybe_result); | 347 USE(maybe_result); |
| 349 #ifdef DEBUG | 348 #ifdef DEBUG |
| 350 Object* result; | 349 Object* result; |
| 351 // Dictionary has been allocated with sufficient size for all elements. | 350 // Dictionary has been allocated with sufficient size for all elements. |
| 352 ASSERT(maybe_result->ToObject(&result)); | 351 ASSERT(maybe_result->ToObject(&result)); |
| 353 ASSERT(*dictionary_ == result); | 352 ASSERT(*dictionary_ == result); |
| 354 #endif | 353 #endif |
| 355 } | 354 } |
| 356 | 355 |
| 357 | 356 |
| 358 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { | 357 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { |
| 359 Isolate* isolate = Isolate::Current(); | 358 Isolate* isolate = Isolate::Current(); |
| 360 HandleScope scope(isolate); | 359 HandleScope scope(isolate); |
| 361 | 360 |
| 362 const int kInitialCapacity = 16; | 361 const int kInitialCapacity = 16; |
| 363 List<int> code_positions(kInitialCapacity); | 362 List<int> code_positions(kInitialCapacity); |
| 364 List<unsigned> ast_ids(kInitialCapacity); | 363 List<int> source_positions(kInitialCapacity); |
| 365 CollectIds(*code, &code_positions, &ast_ids); | 364 CollectPositions(*code, &code_positions, &source_positions); |
| 366 | 365 |
| 367 ASSERT(dictionary_.is_null()); // Only initialize once. | 366 ASSERT(dictionary_.is_null()); // Only initialize once. |
| 368 dictionary_ = isolate->factory()->NewNumberDictionary( | 367 dictionary_ = isolate->factory()->NewNumberDictionary( |
| 369 code_positions.length()); | 368 code_positions.length()); |
| 370 | 369 |
| 371 const int length = code_positions.length(); | 370 int length = code_positions.length(); |
| 372 ASSERT(ast_ids.length() == length); | 371 ASSERT(source_positions.length() == length); |
| 373 for (int i = 0; i < length; i++) { | 372 for (int i = 0; i < length; i++) { |
| 374 AssertNoAllocation no_allocation; | 373 AssertNoAllocation no_allocation; |
| 375 RelocInfo info(code->instruction_start() + code_positions[i], | 374 RelocInfo info(code->instruction_start() + code_positions[i], |
| 376 RelocInfo::CODE_TARGET, 0); | 375 RelocInfo::CODE_TARGET, 0); |
| 377 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); | 376 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); |
| 378 unsigned id = ast_ids[i]; | 377 int position = source_positions[i]; |
| 379 InlineCacheState state = target->ic_state(); | 378 InlineCacheState state = target->ic_state(); |
| 380 Code::Kind kind = target->kind(); | 379 Code::Kind kind = target->kind(); |
| 381 | 380 |
| 382 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || | 381 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || |
| 383 kind == Code::COMPARE_IC) { | 382 kind == Code::COMPARE_IC) { |
| 384 SetInfo(id, target); | 383 // TODO(kasperl): Avoid having multiple ICs with the same |
| 384 // position by making sure that we have position information |
| 385 // recorded for all binary ICs. |
| 386 int entry = dictionary_->FindEntry(position); |
| 387 if (entry == NumberDictionary::kNotFound) { |
| 388 SetInfo(position, target); |
| 389 } |
| 385 } else if (state == MONOMORPHIC) { | 390 } else if (state == MONOMORPHIC) { |
| 386 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || | 391 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || |
| 387 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { | 392 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { |
| 388 SetInfo(id, target); | 393 SetInfo(position, target); |
| 389 } else if (kind != Code::CALL_IC || | 394 } else if (target->kind() != Code::CALL_IC || |
| 390 target->check_type() == RECEIVER_MAP_CHECK) { | 395 target->check_type() == RECEIVER_MAP_CHECK) { |
| 391 Map* map = target->FindFirstMap(); | 396 Map* map = target->FindFirstMap(); |
| 392 if (map == NULL) { | 397 if (map == NULL) { |
| 393 SetInfo(id, target); | 398 SetInfo(position, target); |
| 394 } else { | 399 } else { |
| 395 SetInfo(id, map); | 400 SetInfo(position, map); |
| 396 } | 401 } |
| 397 } else { | 402 } else { |
| 398 ASSERT(target->kind() == Code::CALL_IC); | 403 ASSERT(target->kind() == Code::CALL_IC); |
| 399 CheckType check = target->check_type(); | 404 CheckType check = target->check_type(); |
| 400 ASSERT(check != RECEIVER_MAP_CHECK); | 405 ASSERT(check != RECEIVER_MAP_CHECK); |
| 401 SetInfo(id, Smi::FromInt(check)); | 406 SetInfo(position, Smi::FromInt(check)); |
| 402 } | 407 } |
| 403 } else if (state == MEGAMORPHIC) { | 408 } else if (state == MEGAMORPHIC) { |
| 404 SetInfo(id, target); | 409 SetInfo(position, target); |
| 405 } | 410 } |
| 406 } | 411 } |
| 407 // Allocate handle in the parent scope. | 412 // Allocate handle in the parent scope. |
| 408 dictionary_ = scope.CloseAndEscape(dictionary_); | 413 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 409 } | 414 } |
| 410 | 415 |
| 411 | 416 |
| 412 void TypeFeedbackOracle::CollectIds(Code* code, | 417 void TypeFeedbackOracle::CollectPositions(Code* code, |
| 413 List<int>* code_positions, | 418 List<int>* code_positions, |
| 414 List<unsigned>* ast_ids) { | 419 List<int>* source_positions) { |
| 415 AssertNoAllocation no_allocation; | 420 AssertNoAllocation no_allocation; |
| 416 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 421 int position = 0; |
| 422 // Because the ICs we use for global variables access in the full |
| 423 // code generator do not have any meaningful positions, we avoid |
| 424 // collecting those by filtering out contextual code targets. |
| 425 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| 426 RelocInfo::kPositionMask; |
| 417 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 427 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
| 418 RelocInfo* info = it.rinfo(); | 428 RelocInfo* info = it.rinfo(); |
| 419 ASSERT(RelocInfo::IsCodeTarget(info->rmode())); | 429 RelocInfo::Mode mode = info->rmode(); |
| 420 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); | 430 if (RelocInfo::IsCodeTarget(mode)) { |
| 421 if (target->is_inline_cache_stub()) { | 431 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); |
| 422 InlineCacheState state = target->ic_state(); | 432 if (target->is_inline_cache_stub()) { |
| 423 Code::Kind kind = target->kind(); | 433 InlineCacheState state = target->ic_state(); |
| 424 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { | 434 Code::Kind kind = target->kind(); |
| 425 if (target->type_recording_binary_op_type() == | 435 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { |
| 426 TRBinaryOpIC::GENERIC) { | 436 if (target->type_recording_binary_op_type() == |
| 427 continue; | 437 TRBinaryOpIC::GENERIC) { |
| 438 continue; |
| 439 } |
| 440 } else if (kind == Code::COMPARE_IC) { |
| 441 if (target->compare_state() == CompareIC::GENERIC) continue; |
| 442 } else { |
| 443 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; |
| 428 } | 444 } |
| 429 } else if (kind == Code::COMPARE_IC) { | 445 code_positions->Add( |
| 430 if (target->compare_state() == CompareIC::GENERIC) continue; | 446 static_cast<int>(info->pc() - code->instruction_start())); |
| 431 } else { | 447 source_positions->Add(position); |
| 432 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; | |
| 433 } | 448 } |
| 434 code_positions->Add( | 449 } else { |
| 435 static_cast<int>(info->pc() - code->instruction_start())); | 450 ASSERT(RelocInfo::IsPosition(mode)); |
| 436 ast_ids->Add(static_cast<unsigned>(info->data())); | 451 position = static_cast<int>(info->data()); |
| 437 } | 452 } |
| 438 } | 453 } |
| 439 } | 454 } |
| 440 | 455 |
| 441 } } // namespace v8::internal | 456 } } // namespace v8::internal |
| OLD | NEW |