Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: src/type-info.cc

Issue 6624085: [Isolates] Merge 7051:7083 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/type-info.h ('k') | src/version.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 return info; 57 return info;
58 } 58 }
59 59
60 60
61 STATIC_ASSERT(DEFAULT_STRING_STUB == Code::kNoExtraICState); 61 STATIC_ASSERT(DEFAULT_STRING_STUB == Code::kNoExtraICState);
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 Initialize(code); 67 PopulateMap(code);
68 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue);
68 } 69 }
69 70
70 71
71 void TypeFeedbackOracle::Initialize(Handle<Code> code) { 72 Handle<Object> TypeFeedbackOracle::GetInfo(int pos) {
72 Isolate* isolate = Isolate::Current(); 73 int entry = dictionary_->FindEntry(pos);
73 ASSERT(map_.is_null()); // Only initialize once. 74 return entry != NumberDictionary::kNotFound
74 map_ = isolate->factory()->NewJSObject(isolate->object_function()); 75 ? Handle<Object>(dictionary_->ValueAt(entry))
75 PopulateMap(code); 76 : Isolate::Current()->factory()->undefined_value();
76 } 77 }
77 78
78 79
79 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) { 80 bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
80 return GetElement(map_, expr->position())->IsMap(); 81 return GetInfo(expr->position())->IsMap();
81 } 82 }
82 83
83 84
84 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) { 85 bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
85 return GetElement(map_, expr->position())->IsMap(); 86 return GetInfo(expr->position())->IsMap();
86 } 87 }
87 88
88 89
89 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { 90 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
90 Handle<Object> value = GetElement(map_, expr->position()); 91 Handle<Object> value = GetInfo(expr->position());
91 return value->IsMap() || value->IsSmi(); 92 return value->IsMap() || value->IsSmi();
92 } 93 }
93 94
94 95
95 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { 96 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
96 ASSERT(LoadIsMonomorphic(expr)); 97 ASSERT(LoadIsMonomorphic(expr));
97 return Handle<Map>::cast(GetElement(map_, expr->position())); 98 return Handle<Map>::cast(GetInfo(expr->position()));
98 } 99 }
99 100
100 101
101 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) { 102 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
102 ASSERT(StoreIsMonomorphic(expr)); 103 ASSERT(StoreIsMonomorphic(expr));
103 return Handle<Map>::cast(GetElement(map_, expr->position())); 104 return Handle<Map>::cast(GetInfo(expr->position()));
104 } 105 }
105 106
106 107
107 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr, 108 ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
108 Handle<String> name) { 109 Handle<String> name) {
109 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); 110 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
110 return CollectReceiverTypes(expr->position(), name, flags); 111 return CollectReceiverTypes(expr->position(), name, flags);
111 } 112 }
112 113
113 114
(...skipping 15 matching lines...) Expand all
129 NORMAL, 130 NORMAL,
130 Code::kNoExtraICState, 131 Code::kNoExtraICState,
131 OWN_MAP, 132 OWN_MAP,
132 NOT_IN_LOOP, 133 NOT_IN_LOOP,
133 arity); 134 arity);
134 return CollectReceiverTypes(expr->position(), name, flags); 135 return CollectReceiverTypes(expr->position(), name, flags);
135 } 136 }
136 137
137 138
138 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { 139 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
139 Handle<Object> value = GetElement(map_, expr->position()); 140 Handle<Object> value = GetInfo(expr->position());
140 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; 141 if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
141 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); 142 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
142 ASSERT(check != RECEIVER_MAP_CHECK); 143 ASSERT(check != RECEIVER_MAP_CHECK);
143 return check; 144 return check;
144 } 145 }
145 146
146 147
147 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( 148 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
148 CheckType check) { 149 CheckType check) {
149 JSFunction* function = NULL; 150 JSFunction* function = NULL;
(...skipping 10 matching lines...) Expand all
160 case BOOLEAN_CHECK: 161 case BOOLEAN_CHECK:
161 function = global_context_->boolean_function(); 162 function = global_context_->boolean_function();
162 break; 163 break;
163 } 164 }
164 ASSERT(function != NULL); 165 ASSERT(function != NULL);
165 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); 166 return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
166 } 167 }
167 168
168 169
169 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { 170 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
170 Handle<Object> object = GetElement(map_, expr->position()); 171 return *GetInfo(expr->position()) ==
171 return *object == Isolate::Current()->builtins()->builtin(id); 172 Isolate::Current()->builtins()->builtin(id);
172 } 173 }
173 174
174 175
175 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { 176 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
176 Handle<Object> object = GetElement(map_, expr->position()); 177 Handle<Object> object = GetInfo(expr->position());
177 TypeInfo unknown = TypeInfo::Unknown(); 178 TypeInfo unknown = TypeInfo::Unknown();
178 if (!object->IsCode()) return unknown; 179 if (!object->IsCode()) return unknown;
179 Handle<Code> code = Handle<Code>::cast(object); 180 Handle<Code> code = Handle<Code>::cast(object);
180 if (!code->is_compare_ic_stub()) return unknown; 181 if (!code->is_compare_ic_stub()) return unknown;
181 182
182 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 183 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
183 switch (state) { 184 switch (state) {
184 case CompareIC::UNINITIALIZED: 185 case CompareIC::UNINITIALIZED:
185 // Uninitialized means never executed. 186 // Uninitialized means never executed.
186 // TODO(fschneider): Introduce a separate value for never-executed ICs. 187 // TODO(fschneider): Introduce a separate value for never-executed ICs.
187 return unknown; 188 return unknown;
188 case CompareIC::SMIS: 189 case CompareIC::SMIS:
189 return TypeInfo::Smi(); 190 return TypeInfo::Smi();
190 case CompareIC::HEAP_NUMBERS: 191 case CompareIC::HEAP_NUMBERS:
191 return TypeInfo::Number(); 192 return TypeInfo::Number();
192 case CompareIC::OBJECTS: 193 case CompareIC::OBJECTS:
193 // TODO(kasperl): We really need a type for JS objects here. 194 // TODO(kasperl): We really need a type for JS objects here.
194 return TypeInfo::NonPrimitive(); 195 return TypeInfo::NonPrimitive();
195 case CompareIC::GENERIC: 196 case CompareIC::GENERIC:
196 default: 197 default:
197 return unknown; 198 return unknown;
198 } 199 }
199 } 200 }
200 201
201 202
202 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { 203 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) {
203 Handle<Object> object = GetElement(map_, expr->position()); 204 Handle<Object> object = GetInfo(expr->position());
204 TypeInfo unknown = TypeInfo::Unknown(); 205 TypeInfo unknown = TypeInfo::Unknown();
205 if (!object->IsCode()) return unknown; 206 if (!object->IsCode()) return unknown;
206 Handle<Code> code = Handle<Code>::cast(object); 207 Handle<Code> code = Handle<Code>::cast(object);
207 if (code->is_binary_op_stub()) { 208 if (code->is_binary_op_stub()) {
208 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 209 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
209 code->binary_op_type()); 210 code->binary_op_type());
210 switch (type) { 211 switch (type) {
211 case BinaryOpIC::UNINIT_OR_SMI: 212 case BinaryOpIC::UNINIT_OR_SMI:
212 return TypeInfo::Smi(); 213 return TypeInfo::Smi();
213 case BinaryOpIC::DEFAULT: 214 case BinaryOpIC::DEFAULT:
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 return unknown; 256 return unknown;
256 default: 257 default:
257 return unknown; 258 return unknown;
258 } 259 }
259 } 260 }
260 return unknown; 261 return unknown;
261 } 262 }
262 263
263 264
264 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { 265 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
265 Handle<Object> object = GetElement(map_, clause->position()); 266 Handle<Object> object = GetInfo(clause->position());
266 TypeInfo unknown = TypeInfo::Unknown(); 267 TypeInfo unknown = TypeInfo::Unknown();
267 if (!object->IsCode()) return unknown; 268 if (!object->IsCode()) return unknown;
268 Handle<Code> code = Handle<Code>::cast(object); 269 Handle<Code> code = Handle<Code>::cast(object);
269 if (!code->is_compare_ic_stub()) return unknown; 270 if (!code->is_compare_ic_stub()) return unknown;
270 271
271 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 272 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
272 switch (state) { 273 switch (state) {
273 case CompareIC::UNINITIALIZED: 274 case CompareIC::UNINITIALIZED:
274 // Uninitialized means never executed. 275 // Uninitialized means never executed.
275 // TODO(fschneider): Introduce a separate value for never-executed ICs. 276 // TODO(fschneider): Introduce a separate value for never-executed ICs.
276 return unknown; 277 return unknown;
277 case CompareIC::SMIS: 278 case CompareIC::SMIS:
278 return TypeInfo::Smi(); 279 return TypeInfo::Smi();
279 case CompareIC::HEAP_NUMBERS: 280 case CompareIC::HEAP_NUMBERS:
280 return TypeInfo::Number(); 281 return TypeInfo::Number();
281 case CompareIC::OBJECTS: 282 case CompareIC::OBJECTS:
282 // TODO(kasperl): We really need a type for JS objects here. 283 // TODO(kasperl): We really need a type for JS objects here.
283 return TypeInfo::NonPrimitive(); 284 return TypeInfo::NonPrimitive();
284 case CompareIC::GENERIC: 285 case CompareIC::GENERIC:
285 default: 286 default:
286 return unknown; 287 return unknown;
287 } 288 }
288 } 289 }
289 290
290 291
291 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position, 292 ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position,
292 Handle<String> name, 293 Handle<String> name,
293 Code::Flags flags) { 294 Code::Flags flags) {
294 Isolate* isolate = Isolate::Current(); 295 Isolate* isolate = Isolate::Current();
295 Handle<Object> object = GetElement(map_, position); 296 Handle<Object> object = GetInfo(position);
296 if (object->IsUndefined() || object->IsSmi()) return NULL; 297 if (object->IsUndefined() || object->IsSmi()) return NULL;
297 298
298 if (*object == isolate->builtins()->builtin(Builtins::StoreIC_GlobalProxy)) { 299 if (*object == isolate->builtins()->builtin(Builtins::StoreIC_GlobalProxy)) {
299 // TODO(fschneider): We could collect the maps and signal that 300 // TODO(fschneider): We could collect the maps and signal that
300 // we need a generic store (or load) here. 301 // we need a generic store (or load) here.
301 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC); 302 ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
302 return NULL; 303 return NULL;
303 } else if (object->IsMap()) { 304 } else if (object->IsMap()) {
304 ZoneMapList* types = new ZoneMapList(1); 305 ZoneMapList* types = new ZoneMapList(1);
305 types->Add(Handle<Map>::cast(object)); 306 types->Add(Handle<Map>::cast(object));
306 return types; 307 return types;
307 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { 308 } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
308 ZoneMapList* types = new ZoneMapList(4); 309 ZoneMapList* types = new ZoneMapList(4);
309 ASSERT(object->IsCode()); 310 ASSERT(object->IsCode());
310 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); 311 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags);
311 return types->length() > 0 ? types : NULL; 312 return types->length() > 0 ? types : NULL;
312 } else { 313 } else {
313 return NULL; 314 return NULL;
314 } 315 }
315 } 316 }
316 317
317 318
318 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { 319 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
319 HandleScope scope; 320 Isolate* isolate = Isolate::Current();
321 HandleScope scope(isolate);
320 322
321 const int kInitialCapacity = 16; 323 const int kInitialCapacity = 16;
322 List<int> code_positions(kInitialCapacity); 324 List<int> code_positions(kInitialCapacity);
323 List<int> source_positions(kInitialCapacity); 325 List<int> source_positions(kInitialCapacity);
324 CollectPositions(*code, &code_positions, &source_positions); 326 CollectPositions(*code, &code_positions, &source_positions);
325 327
328 ASSERT(dictionary_.is_null()); // Only initialize once.
329 dictionary_ = isolate->factory()->NewNumberDictionary(
330 code_positions.length());
331
326 int length = code_positions.length(); 332 int length = code_positions.length();
327 ASSERT(source_positions.length() == length); 333 ASSERT(source_positions.length() == length);
328 for (int i = 0; i < length; i++) { 334 for (int i = 0; i < length; i++) {
335 HandleScope loop_scope(isolate);
329 RelocInfo info(code->instruction_start() + code_positions[i], 336 RelocInfo info(code->instruction_start() + code_positions[i],
330 RelocInfo::CODE_TARGET, 0); 337 RelocInfo::CODE_TARGET, 0);
331 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address())); 338 Handle<Code> target(Code::GetCodeFromTargetAddress(info.target_address()));
332 int position = source_positions[i]; 339 int position = source_positions[i];
333 InlineCacheState state = target->ic_state(); 340 InlineCacheState state = target->ic_state();
334 Code::Kind kind = target->kind(); 341 Code::Kind kind = target->kind();
342 Handle<Object> value;
335 if (kind == Code::BINARY_OP_IC || 343 if (kind == Code::BINARY_OP_IC ||
336 kind == Code::TYPE_RECORDING_BINARY_OP_IC || 344 kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
337 kind == Code::COMPARE_IC) { 345 kind == Code::COMPARE_IC) {
338 // TODO(kasperl): Avoid having multiple ICs with the same 346 // TODO(kasperl): Avoid having multiple ICs with the same
339 // position by making sure that we have position information 347 // position by making sure that we have position information
340 // recorded for all binary ICs. 348 // recorded for all binary ICs.
341 if (GetElement(map_, position)->IsUndefined()) { 349 int entry = dictionary_->FindEntry(position);
342 SetElement(map_, position, target); 350 if (entry == NumberDictionary::kNotFound) {
351 value = target;
343 } 352 }
344 } else if (state == MONOMORPHIC) { 353 } else if (state == MONOMORPHIC) {
345 if (target->kind() != Code::CALL_IC || 354 if (target->kind() != Code::CALL_IC ||
346 target->check_type() == RECEIVER_MAP_CHECK) { 355 target->check_type() == RECEIVER_MAP_CHECK) {
347 Map* map = target->FindFirstMap(); 356 Map* map = target->FindFirstMap();
348 if (map == NULL) { 357 if (map == NULL) {
349 SetElement(map_, position, target); 358 value = target;
350 } else { 359 } else {
351 SetElement(map_, position, Handle<Map>(map)); 360 value = Handle<Map>(map);
352 } 361 }
353 } else { 362 } else {
354 ASSERT(target->kind() == Code::CALL_IC); 363 ASSERT(target->kind() == Code::CALL_IC);
355 CheckType check = target->check_type(); 364 CheckType check = target->check_type();
356 ASSERT(check != RECEIVER_MAP_CHECK); 365 ASSERT(check != RECEIVER_MAP_CHECK);
357 SetElement(map_, position, Handle<Object>(Smi::FromInt(check))); 366 value = Handle<Object>(Smi::FromInt(check));
358 ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
359 } 367 }
360 } else if (state == MEGAMORPHIC) { 368 } else if (state == MEGAMORPHIC) {
361 SetElement(map_, position, target); 369 value = target;
370 }
371
372 if (!value.is_null()) {
373 Handle<NumberDictionary> new_dict =
374 isolate->factory()->DictionaryAtNumberPut(
375 dictionary_, position, value);
376 dictionary_ = loop_scope.CloseAndEscape(new_dict);
362 } 377 }
363 } 378 }
379 // Allocate handle in the parent scope.
380 dictionary_ = scope.CloseAndEscape(dictionary_);
364 } 381 }
365 382
366 383
367 void TypeFeedbackOracle::CollectPositions(Code* code, 384 void TypeFeedbackOracle::CollectPositions(Code* code,
368 List<int>* code_positions, 385 List<int>* code_positions,
369 List<int>* source_positions) { 386 List<int>* source_positions) {
370 AssertNoAllocation no_allocation; 387 AssertNoAllocation no_allocation;
371 int position = 0; 388 int position = 0;
372 // Because the ICs we use for global variables access in the full 389 // Because the ICs we use for global variables access in the full
373 // code generator do not have any meaningful positions, we avoid 390 // code generator do not have any meaningful positions, we avoid
(...skipping 25 matching lines...) Expand all
399 source_positions->Add(position); 416 source_positions->Add(position);
400 } 417 }
401 } else { 418 } else {
402 ASSERT(RelocInfo::IsPosition(mode)); 419 ASSERT(RelocInfo::IsPosition(mode));
403 position = static_cast<int>(info->data()); 420 position = static_cast<int>(info->data());
404 } 421 }
405 } 422 }
406 } 423 }
407 424
408 } } // namespace v8::internal 425 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | src/version.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698