Chromium Code Reviews| 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(int pos) { | 72 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { |
| 73 int entry = dictionary_->FindEntry(pos); | 73 int entry = dictionary_->FindEntry(ast_id); |
| 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->position())); | 81 Handle<Object> map_or_code(GetInfo(expr->id())); |
| 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->position())); | 93 Handle<Object> map_or_code(GetInfo(expr->id())); |
| 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->position()); | 105 Handle<Object> value = GetInfo(expr->id()); |
| 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->position()))); | 113 Handle<HeapObject>::cast(GetInfo(expr->id()))); |
| 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->position()))); | 125 Handle<HeapObject>::cast(GetInfo(expr->id()))); |
| 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->position(), name, flags); | 137 return CollectReceiverTypes(expr->id(), 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->position(), name, flags); | 144 return CollectReceiverTypes(expr->id(), 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->position(), name, flags); | 161 return CollectReceiverTypes(expr->id(), 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->position()); | 166 Handle<Object> value = GetInfo(expr->id()); |
| 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->position()); | 175 Handle<Object> stub = GetInfo(expr->id()); |
| 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->position()); | 182 Handle<Object> stub = GetInfo(expr->id()); |
| 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->position()) == | 210 return *GetInfo(expr->id()) == |
| 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->position()); | 216 Handle<Object> object = GetInfo(expr->id()); |
| 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->position()); | 243 Handle<Object> object = GetInfo(expr->id()); |
| 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 26 matching lines...) Expand all Loading... | |
| 280 return unknown; | 280 return unknown; |
| 281 default: | 281 default: |
| 282 return unknown; | 282 return unknown; |
| 283 } | 283 } |
| 284 } | 284 } |
| 285 return unknown; | 285 return unknown; |
| 286 } | 286 } |
| 287 | 287 |
| 288 | 288 |
| 289 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { | 289 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { |
| 290 Handle<Object> object = GetInfo(clause->position()); | 290 Handle<Object> object = GetInfo(clause->label()->id()); |
| 291 TypeInfo unknown = TypeInfo::Unknown(); | 291 TypeInfo unknown = TypeInfo::Unknown(); |
| 292 if (!object->IsCode()) return unknown; | 292 if (!object->IsCode()) return unknown; |
| 293 Handle<Code> code = Handle<Code>::cast(object); | 293 Handle<Code> code = Handle<Code>::cast(object); |
| 294 if (!code->is_compare_ic_stub()) return unknown; | 294 if (!code->is_compare_ic_stub()) return unknown; |
| 295 | 295 |
| 296 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); | 296 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); |
| 297 switch (state) { | 297 switch (state) { |
| 298 case CompareIC::UNINITIALIZED: | 298 case CompareIC::UNINITIALIZED: |
| 299 // Uninitialized means never executed. | 299 // Uninitialized means never executed. |
| 300 // TODO(fschneider): Introduce a separate value for never-executed ICs. | 300 // TODO(fschneider): Introduce a separate value for never-executed ICs. |
| 301 return unknown; | 301 return unknown; |
| 302 case CompareIC::SMIS: | 302 case CompareIC::SMIS: |
| 303 return TypeInfo::Smi(); | 303 return TypeInfo::Smi(); |
| 304 case CompareIC::HEAP_NUMBERS: | 304 case CompareIC::HEAP_NUMBERS: |
| 305 return TypeInfo::Number(); | 305 return TypeInfo::Number(); |
| 306 case CompareIC::OBJECTS: | 306 case CompareIC::OBJECTS: |
| 307 // TODO(kasperl): We really need a type for JS objects here. | 307 // TODO(kasperl): We really need a type for JS objects here. |
| 308 return TypeInfo::NonPrimitive(); | 308 return TypeInfo::NonPrimitive(); |
| 309 case CompareIC::GENERIC: | 309 case CompareIC::GENERIC: |
| 310 default: | 310 default: |
| 311 return unknown; | 311 return unknown; |
| 312 } | 312 } |
| 313 } | 313 } |
| 314 | 314 |
| 315 | 315 |
| 316 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, | 316 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id, |
| 317 Handle<String> name, | 317 Handle<String> name, |
| 318 Code::Flags flags) { | 318 Code::Flags flags) { |
| 319 Isolate* isolate = Isolate::Current(); | 319 Isolate* isolate = Isolate::Current(); |
| 320 Handle<Object> object = GetInfo(position); | 320 Handle<Object> object = GetInfo(ast_id); |
| 321 if (object->IsUndefined() || object->IsSmi()) return NULL; | 321 if (object->IsUndefined() || object->IsSmi()) return NULL; |
| 322 | 322 |
| 323 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { | 323 if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) { |
| 324 // TODO(fschneider): We could collect the maps and signal that | 324 // TODO(fschneider): We could collect the maps and signal that |
| 325 // we need a generic store (or load) here. | 325 // we need a generic store (or load) here. |
| 326 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); | 326 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); |
| 327 return NULL; | 327 return NULL; |
| 328 } else if (object->IsMap()) { | 328 } else if (object->IsMap()) { |
| 329 ZoneMapList* types = new ZoneMapList(1); | 329 ZoneMapList* types = new ZoneMapList(1); |
| 330 types->Add(Handle<Map>::cast(object)); | 330 types->Add(Handle<Map>::cast(object)); |
| 331 return types; | 331 return types; |
| 332 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { | 332 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { |
| 333 ZoneMapList* types = new ZoneMapList(4); | 333 ZoneMapList* types = new ZoneMapList(4); |
| 334 ASSERT(object->IsCode()); | 334 ASSERT(object->IsCode()); |
| 335 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); | 335 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); |
| 336 return types->length() > 0 ? types : NULL; | 336 return types->length() > 0 ? types : NULL; |
| 337 } else { | 337 } else { |
| 338 return NULL; | 338 return NULL; |
| 339 } | 339 } |
| 340 } | 340 } |
| 341 | 341 |
| 342 | 342 |
| 343 void TypeFeedbackOracle::SetInfo(int position, Object* target) { | 343 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { |
| 344 MaybeObject* maybe_result = dictionary_->AtNumberPut(position, target); | 344 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); |
|
Vitaly Repeshko
2011/04/15 01:24:43
It used to work fine with an extra assert that we
William Hesse
2011/04/15 11:51:27
Done.
| |
| 345 USE(maybe_result); | 345 USE(maybe_result); |
| 346 #ifdef DEBUG | 346 #ifdef DEBUG |
| 347 Object* result; | 347 Object* result; |
| 348 // Dictionary has been allocated with sufficient size for all elements. | 348 // Dictionary has been allocated with sufficient size for all elements. |
| 349 ASSERT(maybe_result->ToObject(&result)); | 349 ASSERT(maybe_result->ToObject(&result)); |
| 350 ASSERT(*dictionary_ == result); | 350 ASSERT(*dictionary_ == result); |
| 351 #endif | 351 #endif |
| 352 } | 352 } |
| 353 | 353 |
| 354 | 354 |
| 355 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { | 355 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { |
| 356 Isolate* isolate = Isolate::Current(); | 356 Isolate* isolate = Isolate::Current(); |
| 357 HandleScope scope(isolate); | 357 HandleScope scope(isolate); |
| 358 | 358 |
| 359 const int kInitialCapacity = 16; | 359 const int kInitialCapacity = 16; |
| 360 List<int> code_positions(kInitialCapacity); | 360 List<int> code_positions(kInitialCapacity); |
| 361 List<int> source_positions(kInitialCapacity); | 361 List<unsigned> ast_ids(kInitialCapacity); |
| 362 CollectPositions(*code, &code_positions, &source_positions); | 362 CollectIds(*code, &code_positions, &ast_ids); |
| 363 | 363 |
| 364 ASSERT(dictionary_.is_null()); // Only initialize once. | 364 ASSERT(dictionary_.is_null()); // Only initialize once. |
| 365 dictionary_ = isolate->factory()->NewNumberDictionary( | 365 dictionary_ = isolate->factory()->NewNumberDictionary( |
| 366 code_positions.length()); | 366 code_positions.length()); |
| 367 | 367 |
| 368 int length = code_positions.length(); | 368 const int length = code_positions.length(); |
| 369 ASSERT(source_positions.length() == length); | 369 ASSERT(ast_ids.length() == length); |
| 370 for (int i = 0; i < length; i++) { | 370 for (int i = 0; i < length; i++) { |
| 371 AssertNoAllocation no_allocation; | 371 AssertNoAllocation no_allocation; |
| 372 RelocInfo info(code->instruction_start() + code_positions[i], | 372 RelocInfo info(code->instruction_start() + code_positions[i], |
| 373 RelocInfo::CODE_TARGET, 0); | 373 RelocInfo::CODE_TARGET, 0); |
| 374 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); | 374 Code* target = Code::GetCodeFromTargetAddress(info.target_address()); |
| 375 int position = source_positions[i]; | 375 unsigned id = ast_ids[i]; |
| 376 InlineCacheState state = target->ic_state(); | 376 InlineCacheState state = target->ic_state(); |
| 377 Code::Kind kind = target->kind(); | 377 Code::Kind kind = target->kind(); |
| 378 | 378 |
| 379 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || | 379 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || |
| 380 kind == Code::COMPARE_IC) { | 380 kind == Code::COMPARE_IC) { |
| 381 // TODO(kasperl): Avoid having multiple ICs with the same | 381 SetInfo(id, target); |
| 382 // position by making sure that we have position information | |
| 383 // recorded for all binary ICs. | |
| 384 int entry = dictionary_->FindEntry(position); | |
| 385 if (entry == NumberDictionary::kNotFound) { | |
| 386 SetInfo(position, target); | |
| 387 } | |
| 388 } else if (state == MONOMORPHIC) { | 382 } else if (state == MONOMORPHIC) { |
| 389 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || | 383 if (kind == Code::KEYED_EXTERNAL_ARRAY_LOAD_IC || |
| 390 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { | 384 kind == Code::KEYED_EXTERNAL_ARRAY_STORE_IC) { |
| 391 SetInfo(position, target); | 385 SetInfo(id, target); |
| 392 } else if (target->kind() != Code::CALL_IC || | 386 } else if (kind != Code::CALL_IC || |
| 393 target->check_type() == RECEIVER_MAP_CHECK) { | 387 target->check_type() == RECEIVER_MAP_CHECK) { |
| 394 Map* map = target->FindFirstMap(); | 388 Map* map = target->FindFirstMap(); |
| 395 if (map == NULL) { | 389 if (map == NULL) { |
| 396 SetInfo(position, target); | 390 SetInfo(id, target); |
| 397 } else { | 391 } else { |
| 398 SetInfo(position, map); | 392 SetInfo(id, map); |
| 399 } | 393 } |
| 400 } else { | 394 } else { |
| 401 ASSERT(target->kind() == Code::CALL_IC); | 395 ASSERT(target->kind() == Code::CALL_IC); |
| 402 CheckType check = target->check_type(); | 396 CheckType check = target->check_type(); |
| 403 ASSERT(check != RECEIVER_MAP_CHECK); | 397 ASSERT(check != RECEIVER_MAP_CHECK); |
| 404 SetInfo(position, Smi::FromInt(check)); | 398 SetInfo(id, Smi::FromInt(check)); |
| 405 } | 399 } |
| 406 } else if (state == MEGAMORPHIC) { | 400 } else if (state == MEGAMORPHIC) { |
| 407 SetInfo(position, target); | 401 SetInfo(id, target); |
| 408 } | 402 } |
| 409 } | 403 } |
| 410 // Allocate handle in the parent scope. | 404 // Allocate handle in the parent scope. |
| 411 dictionary_ = scope.CloseAndEscape(dictionary_); | 405 dictionary_ = scope.CloseAndEscape(dictionary_); |
| 412 } | 406 } |
| 413 | 407 |
| 414 | 408 |
| 415 void TypeFeedbackOracle::CollectPositions(Code* code, | 409 void TypeFeedbackOracle::CollectIds(Code* code, |
| 416 List<int>* code_positions, | 410 List<int>* code_positions, |
|
Vitaly Repeshko
2011/04/15 01:24:43
nit: Fix indentation.
| |
| 417 List<int>* source_positions) { | 411 List<unsigned>* ast_ids) { |
| 418 AssertNoAllocation no_allocation; | 412 AssertNoAllocation no_allocation; |
| 419 int position = 0; | 413 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 420 // Because the ICs we use for global variables access in the full | |
| 421 // code generator do not have any meaningful positions, we avoid | |
| 422 // collecting those by filtering out contextual code targets. | |
| 423 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | |
| 424 RelocInfo::kPositionMask; | |
| 425 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 414 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
| 426 RelocInfo* info = it.rinfo(); | 415 RelocInfo* info = it.rinfo(); |
| 427 RelocInfo::Mode mode = info->rmode(); | 416 RelocInfo::Mode mode = info->rmode(); |
| 428 if (RelocInfo::IsCodeTarget(mode)) { | 417 if (RelocInfo::IsCodeTarget(mode)) { |
|
Vitaly Repeshko
2011/04/15 01:24:43
This can be turned into an assert.
William Hesse
2011/04/15 11:51:27
Done.
| |
| 429 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); | 418 Code* target = Code::GetCodeFromTargetAddress(info->target_address()); |
| 430 if (target->is_inline_cache_stub()) { | 419 if (target->is_inline_cache_stub()) { |
| 431 InlineCacheState state = target->ic_state(); | 420 InlineCacheState state = target->ic_state(); |
| 432 Code::Kind kind = target->kind(); | 421 Code::Kind kind = target->kind(); |
| 433 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { | 422 if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) { |
| 434 if (target->type_recording_binary_op_type() == | 423 if (target->type_recording_binary_op_type() == |
| 435 TRBinaryOpIC::GENERIC) { | 424 TRBinaryOpIC::GENERIC) { |
| 436 continue; | 425 continue; |
| 437 } | 426 } |
| 438 } else if (kind == Code::COMPARE_IC) { | 427 } else if (kind == Code::COMPARE_IC) { |
| 439 if (target->compare_state() == CompareIC::GENERIC) continue; | 428 if (target->compare_state() == CompareIC::GENERIC) continue; |
| 440 } else { | 429 } else { |
| 441 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; | 430 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue; |
| 442 } | 431 } |
| 443 code_positions->Add( | 432 code_positions->Add( |
| 444 static_cast<int>(info->pc() - code->instruction_start())); | 433 static_cast<int>(info->pc() - code->instruction_start())); |
| 445 source_positions->Add(position); | 434 ast_ids->Add(static_cast<unsigned>(info->data())); |
| 446 } | 435 } |
| 447 } else { | |
| 448 ASSERT(RelocInfo::IsPosition(mode)); | |
| 449 position = static_cast<int>(info->data()); | |
| 450 } | 436 } |
| 451 } | 437 } |
| 452 } | 438 } |
| 453 | 439 |
| 454 } } // namespace v8::internal | 440 } } // namespace v8::internal |
| OLD | NEW |