| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 primary->value = code; | 95 primary->value = code; |
| 96 primary->map = map; | 96 primary->map = map; |
| 97 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); | 97 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); |
| 98 return code; | 98 return code; |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 Handle<Code> StubCache::FindIC(Handle<Name> name, | 102 Handle<Code> StubCache::FindIC(Handle<Name> name, |
| 103 Handle<Map> stub_holder_map, | 103 Handle<Map> stub_holder_map, |
| 104 Code::Kind kind, | 104 Code::Kind kind, |
| 105 Code::ExtraICState extra_state) { | 105 Code::ExtraICState extra_state, |
| 106 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state); | 106 InlineCacheHolderFlag cache_holder) { |
| 107 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 108 kind, extra_state, cache_holder); |
| 107 Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags), | 109 Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags), |
| 108 isolate_); | 110 isolate_); |
| 109 if (probe->IsCode()) return Handle<Code>::cast(probe); | 111 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 110 return Handle<Code>::null(); | 112 return Handle<Code>::null(); |
| 111 } | 113 } |
| 112 | 114 |
| 113 | 115 |
| 114 Handle<Code> StubCache::FindIC(Handle<Name> name, | |
| 115 Handle<JSObject> stub_holder, | |
| 116 Code::Kind kind, | |
| 117 Code::ExtraICState extra_ic_state) { | |
| 118 return FindIC(name, Handle<Map>(stub_holder->map()), kind, extra_ic_state); | |
| 119 } | |
| 120 | |
| 121 | |
| 122 Handle<Code> StubCache::FindHandler(Handle<Name> name, | 116 Handle<Code> StubCache::FindHandler(Handle<Name> name, |
| 123 Handle<JSObject> receiver, | 117 Handle<HeapObject> stub_holder, |
| 124 Code::Kind kind, | 118 Code::Kind kind, |
| 119 InlineCacheHolderFlag cache_holder, |
| 125 StrictModeFlag strict_mode) { | 120 StrictModeFlag strict_mode) { |
| 126 Code::ExtraICState extra_ic_state = Code::kNoExtraICState; | 121 Code::ExtraICState extra_ic_state = Code::kNoExtraICState; |
| 127 if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { | 122 if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { |
| 128 extra_ic_state = Code::ComputeExtraICState( | 123 extra_ic_state = Code::ComputeExtraICState( |
| 129 STANDARD_STORE, strict_mode); | 124 STANDARD_STORE, strict_mode); |
| 130 } | 125 } |
| 131 Code::Flags flags = Code::ComputeMonomorphicFlags( | 126 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 132 Code::HANDLER, extra_ic_state, Code::NORMAL, kind); | 127 Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind); |
| 133 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 128 |
| 129 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
| 134 isolate_); | 130 isolate_); |
| 135 if (probe->IsCode()) return Handle<Code>::cast(probe); | 131 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 136 return Handle<Code>::null(); | 132 return Handle<Code>::null(); |
| 137 } | 133 } |
| 138 | 134 |
| 139 | 135 |
| 140 Handle<Code> StubCache::ComputeMonomorphicIC(Handle<HeapObject> receiver, | 136 Handle<Code> StubCache::ComputeMonomorphicIC(Handle<Name> name, |
| 137 Handle<Type> type, |
| 141 Handle<Code> handler, | 138 Handle<Code> handler, |
| 142 Handle<Name> name, | |
| 143 StrictModeFlag strict_mode) { | 139 StrictModeFlag strict_mode) { |
| 144 Code::Kind kind = handler->handler_kind(); | 140 Code::Kind kind = handler->handler_kind(); |
| 145 Handle<Map> map(receiver->map()); | 141 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); |
| 146 Handle<Code> ic = FindIC(name, map, kind, strict_mode); | 142 |
| 147 if (!ic.is_null()) return ic; | 143 Handle<Map> stub_holder; |
| 144 Handle<Code> ic; |
| 145 // There are multiple string maps that all use the same prototype. That |
| 146 // prototype cannot hold multiple handlers, one for each of the string maps, |
| 147 // for a single name. Hence, turn off caching of the IC. |
| 148 bool can_be_cached = !type->Is(Type::String()); |
| 149 if (can_be_cached) { |
| 150 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); |
| 151 ic = FindIC(name, stub_holder, kind, strict_mode, flag); |
| 152 if (!ic.is_null()) return ic; |
| 153 } |
| 148 | 154 |
| 149 if (kind == Code::LOAD_IC) { | 155 if (kind == Code::LOAD_IC) { |
| 150 LoadStubCompiler ic_compiler(isolate()); | 156 LoadStubCompiler ic_compiler(isolate(), flag); |
| 151 ic = ic_compiler.CompileMonomorphicIC(map, handler, name); | 157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 152 } else if (kind == Code::KEYED_LOAD_IC) { | 158 } else if (kind == Code::KEYED_LOAD_IC) { |
| 153 KeyedLoadStubCompiler ic_compiler(isolate()); | 159 KeyedLoadStubCompiler ic_compiler(isolate(), flag); |
| 154 ic = ic_compiler.CompileMonomorphicIC(map, handler, name); | 160 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 155 } else if (kind == Code::STORE_IC) { | 161 } else if (kind == Code::STORE_IC) { |
| 156 StoreStubCompiler ic_compiler(isolate(), strict_mode); | 162 StoreStubCompiler ic_compiler(isolate(), strict_mode); |
| 157 ic = ic_compiler.CompileMonomorphicIC(map, handler, name); | 163 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 158 } else { | 164 } else { |
| 159 ASSERT(kind == Code::KEYED_STORE_IC); | 165 ASSERT(kind == Code::KEYED_STORE_IC); |
| 160 KeyedStoreStubCompiler ic_compiler(isolate(), strict_mode, STANDARD_STORE); | 166 KeyedStoreStubCompiler ic_compiler(isolate(), strict_mode, STANDARD_STORE); |
| 161 ic = ic_compiler.CompileMonomorphicIC(map, handler, name); | 167 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); |
| 162 } | 168 } |
| 163 | 169 |
| 164 HeapObject::UpdateMapCodeCache(receiver, name, ic); | 170 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
| 165 return ic; | 171 return ic; |
| 166 } | 172 } |
| 167 | 173 |
| 168 | 174 |
| 169 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, | 175 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, |
| 170 Handle<JSObject> receiver) { | 176 Handle<Object> object) { |
| 177 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); |
| 178 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( |
| 179 isolate(), *object, cache_holder)); |
| 171 // If no global objects are present in the prototype chain, the load | 180 // If no global objects are present in the prototype chain, the load |
| 172 // nonexistent IC stub can be shared for all names for a given map | 181 // nonexistent IC stub can be shared for all names for a given map |
| 173 // and we use the empty string for the map cache in that case. If | 182 // and we use the empty string for the map cache in that case. If |
| 174 // there are global objects involved, we need to check global | 183 // there are global objects involved, we need to check global |
| 175 // property cells in the stub and therefore the stub will be | 184 // property cells in the stub and therefore the stub will be |
| 176 // specific to the name. | 185 // specific to the name. |
| 177 Handle<Name> cache_name = factory()->empty_string(); | 186 Handle<Name> cache_name = factory()->empty_string(); |
| 178 Handle<JSObject> current; | 187 Handle<JSObject> current; |
| 179 Handle<Object> next = receiver; | 188 Handle<Object> next = stub_holder; |
| 180 Handle<JSGlobalObject> global; | 189 Handle<JSGlobalObject> global; |
| 181 do { | 190 do { |
| 182 current = Handle<JSObject>::cast(next); | 191 current = Handle<JSObject>::cast(next); |
| 183 next = Handle<Object>(current->GetPrototype(), isolate_); | 192 next = Handle<Object>(current->GetPrototype(), isolate_); |
| 184 if (current->IsJSGlobalObject()) { | 193 if (current->IsJSGlobalObject()) { |
| 185 global = Handle<JSGlobalObject>::cast(current); | 194 global = Handle<JSGlobalObject>::cast(current); |
| 186 cache_name = name; | 195 cache_name = name; |
| 187 } else if (!current->HasFastProperties()) { | 196 } else if (!current->HasFastProperties()) { |
| 188 cache_name = name; | 197 cache_name = name; |
| 189 } | 198 } |
| 190 } while (!next->IsNull()); | 199 } while (!next->IsNull()); |
| 191 | 200 |
| 192 // Compile the stub that is either shared for all names or | 201 // Compile the stub that is either shared for all names or |
| 193 // name specific if there are global objects involved. | 202 // name specific if there are global objects involved. |
| 194 Handle<Code> handler = FindHandler(cache_name, receiver, Code::LOAD_IC); | 203 Handle<Code> handler = FindHandler( |
| 204 cache_name, stub_holder, Code::LOAD_IC, cache_holder); |
| 195 if (!handler.is_null()) return handler; | 205 if (!handler.is_null()) return handler; |
| 196 | 206 |
| 197 LoadStubCompiler compiler(isolate_); | 207 LoadStubCompiler compiler(isolate_, cache_holder); |
| 198 handler = | 208 handler = |
| 199 compiler.CompileLoadNonexistent(receiver, current, cache_name, global); | 209 compiler.CompileLoadNonexistent(object, current, cache_name, global); |
| 200 HeapObject::UpdateMapCodeCache(receiver, cache_name, handler); | 210 HeapObject::UpdateMapCodeCache(stub_holder, cache_name, handler); |
| 201 return handler; | 211 return handler; |
| 202 } | 212 } |
| 203 | 213 |
| 204 | 214 |
| 205 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 215 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
| 206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 216 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
| 207 Handle<Name> name = | 217 Handle<Name> name = |
| 208 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | 218 isolate()->factory()->KeyedLoadElementMonomorphic_string(); |
| 209 | 219 |
| 210 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 220 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | 260 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
| 251 | 261 |
| 252 Handle<Code> StubCache::ComputeCallConstant(int argc, | 262 Handle<Code> StubCache::ComputeCallConstant(int argc, |
| 253 Code::Kind kind, | 263 Code::Kind kind, |
| 254 Code::ExtraICState extra_state, | 264 Code::ExtraICState extra_state, |
| 255 Handle<Name> name, | 265 Handle<Name> name, |
| 256 Handle<Object> object, | 266 Handle<Object> object, |
| 257 Handle<JSObject> holder, | 267 Handle<JSObject> holder, |
| 258 Handle<JSFunction> function) { | 268 Handle<JSFunction> function) { |
| 259 // Compute the check type and the map. | 269 // Compute the check type and the map. |
| 260 InlineCacheHolderFlag cache_holder = | 270 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); |
| 261 IC::GetCodeCacheForObject(*object, *holder); | 271 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( |
| 262 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( | |
| 263 isolate_, *object, cache_holder)); | 272 isolate_, *object, cache_holder)); |
| 264 | 273 |
| 265 // Compute check type based on receiver/holder. | 274 // Compute check type based on receiver/holder. |
| 266 CheckType check = RECEIVER_MAP_CHECK; | 275 CheckType check = RECEIVER_MAP_CHECK; |
| 267 if (object->IsString()) { | 276 if (object->IsString()) { |
| 268 check = STRING_CHECK; | 277 check = STRING_CHECK; |
| 269 } else if (object->IsSymbol()) { | 278 } else if (object->IsSymbol()) { |
| 270 check = SYMBOL_CHECK; | 279 check = SYMBOL_CHECK; |
| 271 } else if (object->IsNumber()) { | 280 } else if (object->IsNumber()) { |
| 272 check = NUMBER_CHECK; | 281 check = NUMBER_CHECK; |
| 273 } else if (object->IsBoolean()) { | 282 } else if (object->IsBoolean()) { |
| 274 check = BOOLEAN_CHECK; | 283 check = BOOLEAN_CHECK; |
| 275 } | 284 } |
| 276 | 285 |
| 277 if (check != RECEIVER_MAP_CHECK && | 286 if (check != RECEIVER_MAP_CHECK && |
| 278 !function->IsBuiltin() && | 287 !function->IsBuiltin() && |
| 279 function->shared()->is_classic_mode()) { | 288 function->shared()->is_classic_mode()) { |
| 280 // Calling non-strict non-builtins with a value as the receiver | 289 // Calling non-strict non-builtins with a value as the receiver |
| 281 // requires boxing. | 290 // requires boxing. |
| 282 return Handle<Code>::null(); | 291 return Handle<Code>::null(); |
| 283 } | 292 } |
| 284 | 293 |
| 285 Code::Flags flags = Code::ComputeMonomorphicFlags( | 294 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 286 kind, extra_state, Code::CONSTANT, argc, cache_holder); | 295 kind, extra_state, cache_holder, Code::FAST, argc); |
| 287 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | 296 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
| 288 isolate_); | 297 isolate_); |
| 289 if (probe->IsCode()) return Handle<Code>::cast(probe); | 298 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 290 | 299 |
| 291 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | 300 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); |
| 292 Handle<Code> code = | 301 Handle<Code> code = |
| 293 compiler.CompileCallConstant(object, holder, name, check, function); | 302 compiler.CompileCallConstant(object, holder, name, check, function); |
| 294 code->set_check_type(check); | 303 code->set_check_type(check); |
| 295 ASSERT(flags == code->flags()); | 304 ASSERT(flags == code->flags()); |
| 296 PROFILE(isolate_, | 305 PROFILE(isolate_, |
| 297 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 306 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 298 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 307 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 299 | 308 |
| 300 if (CallStubCompiler::CanBeCached(function)) { | 309 if (CallStubCompiler::CanBeCached(function)) { |
| 301 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | 310 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 302 } | 311 } |
| 303 return code; | 312 return code; |
| 304 } | 313 } |
| 305 | 314 |
| 306 | 315 |
| 307 Handle<Code> StubCache::ComputeCallField(int argc, | 316 Handle<Code> StubCache::ComputeCallField(int argc, |
| 308 Code::Kind kind, | 317 Code::Kind kind, |
| 309 Code::ExtraICState extra_state, | 318 Code::ExtraICState extra_state, |
| 310 Handle<Name> name, | 319 Handle<Name> name, |
| 311 Handle<Object> object, | 320 Handle<Object> object, |
| 312 Handle<JSObject> holder, | 321 Handle<JSObject> holder, |
| 313 PropertyIndex index) { | 322 PropertyIndex index) { |
| 314 // Compute the check type and the map. | 323 // Compute the check type and the map. |
| 315 InlineCacheHolderFlag cache_holder = | 324 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); |
| 316 IC::GetCodeCacheForObject(*object, *holder); | 325 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( |
| 317 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( | |
| 318 isolate_, *object, cache_holder)); | 326 isolate_, *object, cache_holder)); |
| 319 | 327 |
| 320 // TODO(1233596): We cannot do receiver map check for non-JS objects | 328 // TODO(1233596): We cannot do receiver map check for non-JS objects |
| 321 // because they may be represented as immediates without a | 329 // because they may be represented as immediates without a |
| 322 // map. Instead, we check against the map in the holder. | 330 // map. Instead, we check against the map in the holder. |
| 323 if (object->IsNumber() || object->IsSymbol() || | 331 if (object->IsNumber() || object->IsSymbol() || |
| 324 object->IsBoolean() || object->IsString()) { | 332 object->IsBoolean() || object->IsString()) { |
| 325 object = holder; | 333 object = holder; |
| 326 } | 334 } |
| 327 | 335 |
| 328 Code::Flags flags = Code::ComputeMonomorphicFlags( | 336 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 329 kind, extra_state, Code::FIELD, argc, cache_holder); | 337 kind, extra_state, cache_holder, Code::FAST, argc); |
| 330 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | 338 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
| 331 isolate_); | 339 isolate_); |
| 332 if (probe->IsCode()) return Handle<Code>::cast(probe); | 340 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 333 | 341 |
| 334 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | 342 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); |
| 335 Handle<Code> code = | 343 Handle<Code> code = |
| 336 compiler.CompileCallField(Handle<JSObject>::cast(object), | 344 compiler.CompileCallField(Handle<JSObject>::cast(object), |
| 337 holder, index, name); | 345 holder, index, name); |
| 338 ASSERT(flags == code->flags()); | 346 ASSERT(flags == code->flags()); |
| 339 PROFILE(isolate_, | 347 PROFILE(isolate_, |
| 340 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 348 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 341 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 349 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 342 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | 350 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 343 return code; | 351 return code; |
| 344 } | 352 } |
| 345 | 353 |
| 346 | 354 |
| 347 Handle<Code> StubCache::ComputeCallInterceptor(int argc, | 355 Handle<Code> StubCache::ComputeCallInterceptor(int argc, |
| 348 Code::Kind kind, | 356 Code::Kind kind, |
| 349 Code::ExtraICState extra_state, | 357 Code::ExtraICState extra_state, |
| 350 Handle<Name> name, | 358 Handle<Name> name, |
| 351 Handle<Object> object, | 359 Handle<Object> object, |
| 352 Handle<JSObject> holder) { | 360 Handle<JSObject> holder) { |
| 353 // Compute the check type and the map. | 361 // Compute the check type and the map. |
| 354 InlineCacheHolderFlag cache_holder = | 362 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); |
| 355 IC::GetCodeCacheForObject(*object, *holder); | 363 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( |
| 356 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( | |
| 357 isolate_, *object, cache_holder)); | 364 isolate_, *object, cache_holder)); |
| 358 | 365 |
| 359 // TODO(1233596): We cannot do receiver map check for non-JS objects | 366 // TODO(1233596): We cannot do receiver map check for non-JS objects |
| 360 // because they may be represented as immediates without a | 367 // because they may be represented as immediates without a |
| 361 // map. Instead, we check against the map in the holder. | 368 // map. Instead, we check against the map in the holder. |
| 362 if (object->IsNumber() || object->IsSymbol() || | 369 if (object->IsNumber() || object->IsSymbol() || |
| 363 object->IsBoolean() || object->IsString()) { | 370 object->IsBoolean() || object->IsString()) { |
| 364 object = holder; | 371 object = holder; |
| 365 } | 372 } |
| 366 | 373 |
| 367 Code::Flags flags = Code::ComputeMonomorphicFlags( | 374 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 368 kind, extra_state, Code::INTERCEPTOR, argc, cache_holder); | 375 kind, extra_state, cache_holder, Code::FAST, argc); |
| 369 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | 376 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
| 370 isolate_); | 377 isolate_); |
| 371 if (probe->IsCode()) return Handle<Code>::cast(probe); | 378 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 372 | 379 |
| 373 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); | 380 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); |
| 374 Handle<Code> code = | 381 Handle<Code> code = |
| 375 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object), | 382 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object), |
| 376 holder, name); | 383 holder, name); |
| 377 ASSERT(flags == code->flags()); | 384 ASSERT(flags == code->flags()); |
| 378 PROFILE(isolate(), | 385 PROFILE(isolate(), |
| 379 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 386 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 380 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 387 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 381 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | 388 HeapObject::UpdateMapCodeCache(stub_holder, name, code); |
| 382 return code; | 389 return code; |
| 383 } | 390 } |
| 384 | 391 |
| 385 | 392 |
| 386 Handle<Code> StubCache::ComputeCallGlobal(int argc, | 393 Handle<Code> StubCache::ComputeCallGlobal(int argc, |
| 387 Code::Kind kind, | 394 Code::Kind kind, |
| 388 Code::ExtraICState extra_state, | 395 Code::ExtraICState extra_state, |
| 389 Handle<Name> name, | 396 Handle<Name> name, |
| 390 Handle<JSObject> receiver, | 397 Handle<JSObject> receiver, |
| 391 Handle<GlobalObject> holder, | 398 Handle<GlobalObject> holder, |
| 392 Handle<PropertyCell> cell, | 399 Handle<PropertyCell> cell, |
| 393 Handle<JSFunction> function) { | 400 Handle<JSFunction> function) { |
| 394 Code::Flags flags = Code::ComputeMonomorphicFlags( | 401 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 395 kind, extra_state, Code::NORMAL, argc); | 402 kind, extra_state, OWN_MAP, Code::NORMAL, argc); |
| 396 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 403 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
| 397 isolate_); | 404 isolate_); |
| 398 if (probe->IsCode()) return Handle<Code>::cast(probe); | 405 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 399 | 406 |
| 400 CallStubCompiler compiler(isolate(), argc, kind, extra_state); | 407 CallStubCompiler compiler(isolate(), argc, kind, extra_state); |
| 401 Handle<Code> code = | 408 Handle<Code> code = |
| 402 compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 409 compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
| 403 ASSERT(flags == code->flags()); | 410 ASSERT(flags == code->flags()); |
| 404 PROFILE(isolate(), | 411 PROFILE(isolate(), |
| 405 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 412 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 ic->ReplaceNthObject(1, isolate_->heap()->meta_map(), *receiver_map); | 580 ic->ReplaceNthObject(1, isolate_->heap()->meta_map(), *receiver_map); |
| 574 | 581 |
| 575 if (!receiver_map->is_shared()) { | 582 if (!receiver_map->is_shared()) { |
| 576 Map::UpdateCodeCache(receiver_map, name, ic); | 583 Map::UpdateCodeCache(receiver_map, name, ic); |
| 577 } | 584 } |
| 578 | 585 |
| 579 return ic; | 586 return ic; |
| 580 } | 587 } |
| 581 | 588 |
| 582 | 589 |
| 590 // TODO(verwaest): Change this method so it takes in a TypeHandleList. |
| 583 Handle<Code> StubCache::ComputeLoadElementPolymorphic( | 591 Handle<Code> StubCache::ComputeLoadElementPolymorphic( |
| 584 MapHandleList* receiver_maps) { | 592 MapHandleList* receiver_maps) { |
| 585 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 593 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
| 586 Handle<PolymorphicCodeCache> cache = | 594 Handle<PolymorphicCodeCache> cache = |
| 587 isolate_->factory()->polymorphic_code_cache(); | 595 isolate_->factory()->polymorphic_code_cache(); |
| 588 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 596 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 589 if (probe->IsCode()) return Handle<Code>::cast(probe); | 597 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 590 | 598 |
| 599 TypeHandleList types(receiver_maps->length()); |
| 600 for (int i = 0; i < receiver_maps->length(); i++) { |
| 601 types.Add(handle(Type::Class(receiver_maps->at(i)), isolate())); |
| 602 } |
| 591 CodeHandleList handlers(receiver_maps->length()); | 603 CodeHandleList handlers(receiver_maps->length()); |
| 592 KeyedLoadStubCompiler compiler(isolate_); | 604 KeyedLoadStubCompiler compiler(isolate_); |
| 593 compiler.CompileElementHandlers(receiver_maps, &handlers); | 605 compiler.CompileElementHandlers(receiver_maps, &handlers); |
| 594 Handle<Code> code = compiler.CompilePolymorphicIC( | 606 Handle<Code> code = compiler.CompilePolymorphicIC( |
| 595 receiver_maps, &handlers, factory()->empty_string(), | 607 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); |
| 596 Code::NORMAL, ELEMENT); | |
| 597 | 608 |
| 598 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 609 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 599 | 610 |
| 600 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 611 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 601 return code; | 612 return code; |
| 602 } | 613 } |
| 603 | 614 |
| 604 | 615 |
| 605 Handle<Code> StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps, | 616 Handle<Code> StubCache::ComputePolymorphicIC(TypeHandleList* types, |
| 606 CodeHandleList* handlers, | 617 CodeHandleList* handlers, |
| 607 int number_of_valid_maps, | 618 int number_of_valid_types, |
| 608 Handle<Name> name, | 619 Handle<Name> name, |
| 609 StrictModeFlag strict_mode) { | 620 StrictModeFlag strict_mode) { |
| 610 Handle<Code> handler = handlers->at(0); | 621 Handle<Code> handler = handlers->at(0); |
| 611 Code::Kind kind = handler->handler_kind(); | 622 Code::Kind kind = handler->handler_kind(); |
| 612 Code::StubType type = number_of_valid_maps == 1 ? handler->type() | 623 Code::StubType type = number_of_valid_types == 1 ? handler->type() |
| 613 : Code::NORMAL; | 624 : Code::NORMAL; |
| 614 if (kind == Code::LOAD_IC) { | 625 if (kind == Code::LOAD_IC) { |
| 615 LoadStubCompiler ic_compiler(isolate_); | 626 LoadStubCompiler ic_compiler(isolate_); |
| 616 return ic_compiler.CompilePolymorphicIC( | 627 return ic_compiler.CompilePolymorphicIC( |
| 617 receiver_maps, handlers, name, type, PROPERTY); | 628 types, handlers, name, type, PROPERTY); |
| 618 } else { | 629 } else { |
| 619 ASSERT(kind == Code::STORE_IC); | 630 ASSERT(kind == Code::STORE_IC); |
| 620 StoreStubCompiler ic_compiler(isolate_, strict_mode); | 631 StoreStubCompiler ic_compiler(isolate_, strict_mode); |
| 621 return ic_compiler.CompilePolymorphicIC( | 632 return ic_compiler.CompilePolymorphicIC( |
| 622 receiver_maps, handlers, name, type, PROPERTY); | 633 types, handlers, name, type, PROPERTY); |
| 623 } | 634 } |
| 624 } | 635 } |
| 625 | 636 |
| 626 | 637 |
| 627 Handle<Code> StubCache::ComputeStoreElementPolymorphic( | 638 Handle<Code> StubCache::ComputeStoreElementPolymorphic( |
| 628 MapHandleList* receiver_maps, | 639 MapHandleList* receiver_maps, |
| 629 KeyedAccessStoreMode store_mode, | 640 KeyedAccessStoreMode store_mode, |
| 630 StrictModeFlag strict_mode) { | 641 StrictModeFlag strict_mode) { |
| 631 ASSERT(store_mode == STANDARD_STORE || | 642 ASSERT(store_mode == STANDARD_STORE || |
| 632 store_mode == STORE_AND_GROW_NO_TRANSITION || | 643 store_mode == STORE_AND_GROW_NO_TRANSITION || |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 return isolate->heap()->no_interceptor_result_sentinel(); | 830 return isolate->heap()->no_interceptor_result_sentinel(); |
| 820 } | 831 } |
| 821 | 832 |
| 822 | 833 |
| 823 static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) { | 834 static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) { |
| 824 // If the load is non-contextual, just return the undefined result. | 835 // If the load is non-contextual, just return the undefined result. |
| 825 // Note that both keyed and non-keyed loads may end up here, so we | 836 // Note that both keyed and non-keyed loads may end up here, so we |
| 826 // can't use either LoadIC or KeyedLoadIC constructors. | 837 // can't use either LoadIC or KeyedLoadIC constructors. |
| 827 HandleScope scope(isolate); | 838 HandleScope scope(isolate); |
| 828 IC ic(IC::NO_EXTRA_FRAME, isolate); | 839 IC ic(IC::NO_EXTRA_FRAME, isolate); |
| 829 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub()); | 840 ASSERT(ic.IsLoadStub()); |
| 830 if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value(); | 841 if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value(); |
| 831 | 842 |
| 832 // Throw a reference error. | 843 // Throw a reference error. |
| 833 Handle<Name> name_handle(name); | 844 Handle<Name> name_handle(name); |
| 834 Handle<Object> error = | 845 Handle<Object> error = |
| 835 isolate->factory()->NewReferenceError("not_defined", | 846 isolate->factory()->NewReferenceError("not_defined", |
| 836 HandleVector(&name_handle, 1)); | 847 HandleVector(&name_handle, 1)); |
| 837 return isolate->Throw(*error); | 848 return isolate->Throw(*error); |
| 838 } | 849 } |
| 839 | 850 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 #undef CALL_LOGGER_TAG | 1100 #undef CALL_LOGGER_TAG |
| 1090 | 1101 |
| 1091 | 1102 |
| 1092 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, | 1103 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
| 1093 const char* name) { | 1104 const char* name) { |
| 1094 // Create code object in the heap. | 1105 // Create code object in the heap. |
| 1095 CodeDesc desc; | 1106 CodeDesc desc; |
| 1096 masm_.GetCode(&desc); | 1107 masm_.GetCode(&desc); |
| 1097 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); | 1108 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); |
| 1098 #ifdef ENABLE_DISASSEMBLER | 1109 #ifdef ENABLE_DISASSEMBLER |
| 1099 if (FLAG_print_code_stubs) { | 1110 if (FLAG_print_code_stubs) code->Disassemble(name); |
| 1100 CodeTracer::Scope trace_scope(isolate()->GetCodeTracer()); | |
| 1101 code->Disassemble(name, trace_scope.file()); | |
| 1102 } | |
| 1103 #endif | 1111 #endif |
| 1104 return code; | 1112 return code; |
| 1105 } | 1113 } |
| 1106 | 1114 |
| 1107 | 1115 |
| 1108 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, | 1116 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
| 1109 Handle<Name> name) { | 1117 Handle<Name> name) { |
| 1110 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) | 1118 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) |
| 1111 ? GetCodeWithFlags(flags, *Handle<String>::cast(name)->ToCString()) | 1119 ? GetCodeWithFlags(flags, *Handle<String>::cast(name)->ToCString()) |
| 1112 : GetCodeWithFlags(flags, NULL); | 1120 : GetCodeWithFlags(flags, NULL); |
| 1113 } | 1121 } |
| 1114 | 1122 |
| 1115 | 1123 |
| 1116 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, | 1124 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, |
| 1117 Handle<Name> name, | 1125 Handle<Name> name, |
| 1118 LookupResult* lookup) { | 1126 LookupResult* lookup) { |
| 1119 holder->LocalLookupRealNamedProperty(*name, lookup); | 1127 holder->LocalLookupRealNamedProperty(*name, lookup); |
| 1120 if (lookup->IsFound()) return; | 1128 if (lookup->IsFound()) return; |
| 1121 if (holder->GetPrototype()->IsNull()) return; | 1129 if (holder->GetPrototype()->IsNull()) return; |
| 1122 holder->GetPrototype()->Lookup(*name, lookup); | 1130 holder->GetPrototype()->Lookup(*name, lookup); |
| 1123 } | 1131 } |
| 1124 | 1132 |
| 1125 | 1133 |
| 1126 #define __ ACCESS_MASM(masm()) | 1134 #define __ ACCESS_MASM(masm()) |
| 1127 | 1135 |
| 1128 | 1136 |
| 1129 Register LoadStubCompiler::HandlerFrontendHeader( | 1137 Register LoadStubCompiler::HandlerFrontendHeader( |
| 1130 Handle<JSObject> object, | 1138 Handle<Object> object, |
| 1131 Register object_reg, | 1139 Register object_reg, |
| 1132 Handle<JSObject> holder, | 1140 Handle<JSObject> holder, |
| 1133 Handle<Name> name, | 1141 Handle<Name> name, |
| 1134 Label* miss) { | 1142 Label* miss) { |
| 1135 return CheckPrototypes(object, object_reg, holder, | 1143 Handle<JSObject> receiver; |
| 1144 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
| 1145 int function_index = -1; |
| 1146 if (object->IsJSObject()) { |
| 1147 receiver = Handle<JSObject>::cast(object); |
| 1148 check_type = SKIP_RECEIVER; |
| 1149 } else { |
| 1150 if (object->IsString()) { |
| 1151 function_index = Context::STRING_FUNCTION_INDEX; |
| 1152 } else if (object->IsSymbol()) { |
| 1153 function_index = Context::SYMBOL_FUNCTION_INDEX; |
| 1154 } else if (object->IsNumber()) { |
| 1155 function_index = Context::NUMBER_FUNCTION_INDEX; |
| 1156 } else { |
| 1157 ASSERT(object->IsBoolean()); |
| 1158 // Booleans use the generic oddball map, so an additional check is |
| 1159 // needed to ensure the receiver is really a boolean. |
| 1160 GenerateBooleanCheck(object_reg, miss); |
| 1161 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
| 1162 } |
| 1163 |
| 1164 GenerateDirectLoadGlobalFunctionPrototype( |
| 1165 masm(), function_index, scratch1(), miss); |
| 1166 receiver = handle(JSObject::cast(object->GetPrototype(isolate()))); |
| 1167 object_reg = scratch1(); |
| 1168 } |
| 1169 |
| 1170 // Check that the maps starting from the prototype haven't changed. |
| 1171 return CheckPrototypes(receiver, object_reg, holder, |
| 1136 scratch1(), scratch2(), scratch3(), | 1172 scratch1(), scratch2(), scratch3(), |
| 1137 name, miss, SKIP_RECEIVER); | 1173 name, miss, check_type); |
| 1138 } | 1174 } |
| 1139 | 1175 |
| 1140 | 1176 |
| 1141 // HandlerFrontend for store uses the name register. It has to be restored | 1177 // HandlerFrontend for store uses the name register. It has to be restored |
| 1142 // before a miss. | 1178 // before a miss. |
| 1143 Register StoreStubCompiler::HandlerFrontendHeader( | 1179 Register StoreStubCompiler::HandlerFrontendHeader( |
| 1144 Handle<JSObject> object, | 1180 Handle<Object> object, |
| 1145 Register object_reg, | 1181 Register object_reg, |
| 1146 Handle<JSObject> holder, | 1182 Handle<JSObject> holder, |
| 1147 Handle<Name> name, | 1183 Handle<Name> name, |
| 1148 Label* miss) { | 1184 Label* miss) { |
| 1149 return CheckPrototypes(object, object_reg, holder, | 1185 return CheckPrototypes(Handle<JSObject>::cast(object), object_reg, holder, |
| 1150 this->name(), scratch1(), scratch2(), | 1186 this->name(), scratch1(), scratch2(), |
| 1151 name, miss, SKIP_RECEIVER); | 1187 name, miss, SKIP_RECEIVER); |
| 1152 } | 1188 } |
| 1153 | 1189 |
| 1154 | 1190 |
| 1155 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<JSObject> object, | 1191 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { |
| 1192 for (int i = 0; i < types->length(); ++i) { |
| 1193 if (types->at(i)->Is(Type::Number())) return true; |
| 1194 } |
| 1195 return false; |
| 1196 } |
| 1197 |
| 1198 |
| 1199 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Object> object, |
| 1156 Register object_reg, | 1200 Register object_reg, |
| 1157 Handle<JSObject> holder, | 1201 Handle<JSObject> holder, |
| 1158 Handle<Name> name, | 1202 Handle<Name> name) { |
| 1159 Label* success) { | |
| 1160 Label miss; | 1203 Label miss; |
| 1161 | 1204 |
| 1162 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1205 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| 1163 | 1206 |
| 1164 HandlerFrontendFooter(name, success, &miss); | 1207 HandlerFrontendFooter(name, &miss); |
| 1208 |
| 1165 return reg; | 1209 return reg; |
| 1166 } | 1210 } |
| 1167 | 1211 |
| 1168 | 1212 |
| 1169 void LoadStubCompiler::NonexistentHandlerFrontend( | 1213 void LoadStubCompiler::NonexistentHandlerFrontend( |
| 1170 Handle<JSObject> object, | 1214 Handle<Object> object, |
| 1171 Handle<JSObject> last, | 1215 Handle<JSObject> last, |
| 1172 Handle<Name> name, | 1216 Handle<Name> name, |
| 1173 Label* success, | |
| 1174 Handle<JSGlobalObject> global) { | 1217 Handle<JSGlobalObject> global) { |
| 1175 Label miss; | 1218 Label miss; |
| 1176 | 1219 |
| 1177 Register holder = | 1220 Register holder = HandlerFrontendHeader( |
| 1178 HandlerFrontendHeader(object, receiver(), last, name, &miss); | 1221 object, receiver(), last, name, &miss); |
| 1179 | 1222 |
| 1180 if (!last->HasFastProperties() && | 1223 if (!last->HasFastProperties() && |
| 1181 !last->IsJSGlobalObject() && | 1224 !last->IsJSGlobalObject() && |
| 1182 !last->IsJSGlobalProxy()) { | 1225 !last->IsJSGlobalProxy()) { |
| 1183 if (!name->IsUniqueName()) { | 1226 if (!name->IsUniqueName()) { |
| 1184 ASSERT(name->IsString()); | 1227 ASSERT(name->IsString()); |
| 1185 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1228 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1186 } | 1229 } |
| 1187 ASSERT(last->property_dictionary()->FindEntry(*name) == | 1230 ASSERT(last->property_dictionary()->FindEntry(*name) == |
| 1188 NameDictionary::kNotFound); | 1231 NameDictionary::kNotFound); |
| 1189 GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, | 1232 GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, |
| 1190 scratch2(), scratch3()); | 1233 scratch2(), scratch3()); |
| 1191 } | 1234 } |
| 1192 | 1235 |
| 1193 // If the last object in the prototype chain is a global object, | 1236 // If the last object in the prototype chain is a global object, |
| 1194 // check that the global property cell is empty. | 1237 // check that the global property cell is empty. |
| 1195 if (!global.is_null()) { | 1238 if (!global.is_null()) { |
| 1196 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1239 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1197 } | 1240 } |
| 1198 | 1241 |
| 1199 HandlerFrontendFooter(name, success, &miss); | 1242 HandlerFrontendFooter(name, &miss); |
| 1200 } | 1243 } |
| 1201 | 1244 |
| 1202 | 1245 |
| 1203 Handle<Code> LoadStubCompiler::CompileLoadField( | 1246 Handle<Code> LoadStubCompiler::CompileLoadField( |
| 1204 Handle<JSObject> object, | 1247 Handle<Object> object, |
| 1205 Handle<JSObject> holder, | 1248 Handle<JSObject> holder, |
| 1206 Handle<Name> name, | 1249 Handle<Name> name, |
| 1207 PropertyIndex field, | 1250 PropertyIndex field, |
| 1208 Representation representation) { | 1251 Representation representation) { |
| 1209 Label miss; | 1252 Label miss; |
| 1210 | 1253 |
| 1211 Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss); | 1254 Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss); |
| 1212 | 1255 |
| 1213 GenerateLoadField(reg, holder, field, representation); | 1256 GenerateLoadField(reg, holder, field, representation); |
| 1214 | 1257 |
| 1215 __ bind(&miss); | 1258 __ bind(&miss); |
| 1216 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1259 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1217 | 1260 |
| 1218 // Return the generated code. | 1261 // Return the generated code. |
| 1219 return GetCode(kind(), Code::FIELD, name); | 1262 return GetCode(kind(), Code::FAST, name); |
| 1220 } | 1263 } |
| 1221 | 1264 |
| 1222 | 1265 |
| 1223 Handle<Code> LoadStubCompiler::CompileLoadConstant( | 1266 Handle<Code> LoadStubCompiler::CompileLoadConstant( |
| 1224 Handle<JSObject> object, | 1267 Handle<Object> object, |
| 1225 Handle<JSObject> holder, | 1268 Handle<JSObject> holder, |
| 1226 Handle<Name> name, | 1269 Handle<Name> name, |
| 1227 Handle<Object> value) { | 1270 Handle<Object> value) { |
| 1228 Label success; | 1271 HandlerFrontend(object, receiver(), holder, name); |
| 1229 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 1230 __ bind(&success); | |
| 1231 GenerateLoadConstant(value); | 1272 GenerateLoadConstant(value); |
| 1232 | 1273 |
| 1233 // Return the generated code. | 1274 // Return the generated code. |
| 1234 return GetCode(kind(), Code::CONSTANT, name); | 1275 return GetCode(kind(), Code::FAST, name); |
| 1235 } | 1276 } |
| 1236 | 1277 |
| 1237 | 1278 |
| 1238 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 1279 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1239 Handle<JSObject> object, | 1280 Handle<Object> object, |
| 1240 Handle<JSObject> holder, | 1281 Handle<JSObject> holder, |
| 1241 Handle<Name> name, | 1282 Handle<Name> name, |
| 1242 Handle<ExecutableAccessorInfo> callback) { | 1283 Handle<ExecutableAccessorInfo> callback) { |
| 1243 Label success; | |
| 1244 | |
| 1245 Register reg = CallbackHandlerFrontend( | 1284 Register reg = CallbackHandlerFrontend( |
| 1246 object, receiver(), holder, name, &success, callback); | 1285 object, receiver(), holder, name, callback); |
| 1247 __ bind(&success); | |
| 1248 GenerateLoadCallback(reg, callback); | 1286 GenerateLoadCallback(reg, callback); |
| 1249 | 1287 |
| 1250 // Return the generated code. | 1288 // Return the generated code. |
| 1251 return GetCode(kind(), Code::CALLBACKS, name); | 1289 return GetCode(kind(), Code::FAST, name); |
| 1252 } | 1290 } |
| 1253 | 1291 |
| 1254 | 1292 |
| 1255 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 1293 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 1256 Handle<JSObject> object, | 1294 Handle<Object> object, |
| 1257 Handle<JSObject> holder, | 1295 Handle<JSObject> holder, |
| 1258 Handle<Name> name, | 1296 Handle<Name> name, |
| 1259 const CallOptimization& call_optimization) { | 1297 const CallOptimization& call_optimization) { |
| 1260 ASSERT(call_optimization.is_simple_api_call()); | 1298 ASSERT(call_optimization.is_simple_api_call()); |
| 1261 Label success; | |
| 1262 | |
| 1263 Handle<JSFunction> callback = call_optimization.constant_function(); | 1299 Handle<JSFunction> callback = call_optimization.constant_function(); |
| 1264 CallbackHandlerFrontend( | 1300 CallbackHandlerFrontend(object, receiver(), holder, name, callback); |
| 1265 object, receiver(), holder, name, &success, callback); | |
| 1266 __ bind(&success); | |
| 1267 GenerateLoadCallback(call_optimization); | 1301 GenerateLoadCallback(call_optimization); |
| 1268 | 1302 |
| 1269 // Return the generated code. | 1303 // Return the generated code. |
| 1270 return GetCode(kind(), Code::CALLBACKS, name); | 1304 return GetCode(kind(), Code::FAST, name); |
| 1271 } | 1305 } |
| 1272 | 1306 |
| 1273 | 1307 |
| 1274 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( | 1308 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( |
| 1275 Handle<JSObject> object, | 1309 Handle<Object> object, |
| 1276 Handle<JSObject> holder, | 1310 Handle<JSObject> holder, |
| 1277 Handle<Name> name) { | 1311 Handle<Name> name) { |
| 1278 Label success; | |
| 1279 | |
| 1280 LookupResult lookup(isolate()); | 1312 LookupResult lookup(isolate()); |
| 1281 LookupPostInterceptor(holder, name, &lookup); | 1313 LookupPostInterceptor(holder, name, &lookup); |
| 1282 | 1314 |
| 1283 Register reg = HandlerFrontend(object, receiver(), holder, name, &success); | 1315 Register reg = HandlerFrontend(object, receiver(), holder, name); |
| 1284 __ bind(&success); | |
| 1285 // TODO(368): Compile in the whole chain: all the interceptors in | 1316 // TODO(368): Compile in the whole chain: all the interceptors in |
| 1286 // prototypes and ultimate answer. | 1317 // prototypes and ultimate answer. |
| 1287 GenerateLoadInterceptor(reg, object, holder, &lookup, name); | 1318 GenerateLoadInterceptor(reg, object, holder, &lookup, name); |
| 1288 | 1319 |
| 1289 // Return the generated code. | 1320 // Return the generated code. |
| 1290 return GetCode(kind(), Code::INTERCEPTOR, name); | 1321 return GetCode(kind(), Code::FAST, name); |
| 1291 } | 1322 } |
| 1292 | 1323 |
| 1293 | 1324 |
| 1294 void LoadStubCompiler::GenerateLoadPostInterceptor( | 1325 void LoadStubCompiler::GenerateLoadPostInterceptor( |
| 1295 Register interceptor_reg, | 1326 Register interceptor_reg, |
| 1296 Handle<JSObject> interceptor_holder, | 1327 Handle<JSObject> interceptor_holder, |
| 1297 Handle<Name> name, | 1328 Handle<Name> name, |
| 1298 LookupResult* lookup) { | 1329 LookupResult* lookup) { |
| 1299 Label success; | |
| 1300 Handle<JSObject> holder(lookup->holder()); | 1330 Handle<JSObject> holder(lookup->holder()); |
| 1301 if (lookup->IsField()) { | 1331 if (lookup->IsField()) { |
| 1302 PropertyIndex field = lookup->GetFieldIndex(); | 1332 PropertyIndex field = lookup->GetFieldIndex(); |
| 1303 if (interceptor_holder.is_identical_to(holder)) { | 1333 if (interceptor_holder.is_identical_to(holder)) { |
| 1304 GenerateLoadField( | 1334 GenerateLoadField( |
| 1305 interceptor_reg, holder, field, lookup->representation()); | 1335 interceptor_reg, holder, field, lookup->representation()); |
| 1306 } else { | 1336 } else { |
| 1307 // We found FIELD property in prototype chain of interceptor's holder. | 1337 // We found FIELD property in prototype chain of interceptor's holder. |
| 1308 // Retrieve a field from field's holder. | 1338 // Retrieve a field from field's holder. |
| 1309 Register reg = HandlerFrontend( | 1339 Register reg = HandlerFrontend( |
| 1310 interceptor_holder, interceptor_reg, holder, name, &success); | 1340 interceptor_holder, interceptor_reg, holder, name); |
| 1311 __ bind(&success); | |
| 1312 GenerateLoadField( | 1341 GenerateLoadField( |
| 1313 reg, holder, field, lookup->representation()); | 1342 reg, holder, field, lookup->representation()); |
| 1314 } | 1343 } |
| 1315 } else { | 1344 } else { |
| 1316 // We found CALLBACKS property in prototype chain of interceptor's | 1345 // We found CALLBACKS property in prototype chain of interceptor's |
| 1317 // holder. | 1346 // holder. |
| 1318 ASSERT(lookup->type() == CALLBACKS); | 1347 ASSERT(lookup->type() == CALLBACKS); |
| 1319 Handle<ExecutableAccessorInfo> callback( | 1348 Handle<ExecutableAccessorInfo> callback( |
| 1320 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 1349 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 1321 ASSERT(callback->getter() != NULL); | 1350 ASSERT(callback->getter() != NULL); |
| 1322 | 1351 |
| 1323 Register reg = CallbackHandlerFrontend( | 1352 Register reg = CallbackHandlerFrontend( |
| 1324 interceptor_holder, interceptor_reg, holder, name, &success, callback); | 1353 interceptor_holder, interceptor_reg, holder, name, callback); |
| 1325 __ bind(&success); | |
| 1326 GenerateLoadCallback(reg, callback); | 1354 GenerateLoadCallback(reg, callback); |
| 1327 } | 1355 } |
| 1328 } | 1356 } |
| 1329 | 1357 |
| 1330 | 1358 |
| 1331 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( | 1359 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( |
| 1332 Handle<Map> receiver_map, | 1360 Handle<Type> type, |
| 1333 Handle<Code> handler, | 1361 Handle<Code> handler, |
| 1334 Handle<Name> name) { | 1362 Handle<Name> name) { |
| 1335 MapHandleList receiver_maps(1); | 1363 TypeHandleList types(1); |
| 1336 receiver_maps.Add(receiver_map); | |
| 1337 CodeHandleList handlers(1); | 1364 CodeHandleList handlers(1); |
| 1365 types.Add(type); |
| 1338 handlers.Add(handler); | 1366 handlers.Add(handler); |
| 1339 Code::StubType type = handler->type(); | 1367 Code::StubType stub_type = handler->type(); |
| 1340 return CompilePolymorphicIC(&receiver_maps, &handlers, name, type, PROPERTY); | 1368 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); |
| 1341 } | 1369 } |
| 1342 | 1370 |
| 1343 | 1371 |
| 1344 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( | 1372 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( |
| 1345 Handle<JSObject> object, | 1373 Handle<Object> object, |
| 1346 Handle<JSObject> holder, | 1374 Handle<JSObject> holder, |
| 1347 Handle<Name> name, | 1375 Handle<Name> name, |
| 1348 Handle<JSFunction> getter) { | 1376 Handle<JSFunction> getter) { |
| 1349 Label success; | 1377 HandlerFrontend(object, receiver(), holder, name); |
| 1350 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 1351 | |
| 1352 __ bind(&success); | |
| 1353 GenerateLoadViaGetter(masm(), receiver(), getter); | 1378 GenerateLoadViaGetter(masm(), receiver(), getter); |
| 1354 | 1379 |
| 1355 // Return the generated code. | 1380 // Return the generated code. |
| 1356 return GetCode(kind(), Code::CALLBACKS, name); | 1381 return GetCode(kind(), Code::FAST, name); |
| 1357 } | 1382 } |
| 1358 | 1383 |
| 1359 | 1384 |
| 1360 Handle<Code> StoreStubCompiler::CompileStoreTransition( | 1385 Handle<Code> StoreStubCompiler::CompileStoreTransition( |
| 1361 Handle<JSObject> object, | 1386 Handle<JSObject> object, |
| 1362 LookupResult* lookup, | 1387 LookupResult* lookup, |
| 1363 Handle<Map> transition, | 1388 Handle<Map> transition, |
| 1364 Handle<Name> name) { | 1389 Handle<Name> name) { |
| 1365 Label miss, slow; | 1390 Label miss, slow; |
| 1366 | 1391 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1403 &slow); | 1428 &slow); |
| 1404 | 1429 |
| 1405 // Handle store cache miss. | 1430 // Handle store cache miss. |
| 1406 GenerateRestoreName(masm(), &miss, name); | 1431 GenerateRestoreName(masm(), &miss, name); |
| 1407 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1432 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1408 | 1433 |
| 1409 GenerateRestoreName(masm(), &slow, name); | 1434 GenerateRestoreName(masm(), &slow, name); |
| 1410 TailCallBuiltin(masm(), SlowBuiltin(kind())); | 1435 TailCallBuiltin(masm(), SlowBuiltin(kind())); |
| 1411 | 1436 |
| 1412 // Return the generated code. | 1437 // Return the generated code. |
| 1413 return GetCode(kind(), Code::TRANSITION, name); | 1438 return GetCode(kind(), Code::FAST, name); |
| 1414 } | 1439 } |
| 1415 | 1440 |
| 1416 | 1441 |
| 1417 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 1442 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 1418 LookupResult* lookup, | 1443 LookupResult* lookup, |
| 1419 Handle<Name> name) { | 1444 Handle<Name> name) { |
| 1420 Label miss; | 1445 Label miss; |
| 1421 | 1446 |
| 1422 HandlerFrontendHeader(object, receiver(), object, name, &miss); | 1447 HandlerFrontendHeader(object, receiver(), object, name, &miss); |
| 1423 | 1448 |
| 1424 // Generate store field code. | 1449 // Generate store field code. |
| 1425 GenerateStoreField(masm(), | 1450 GenerateStoreField(masm(), |
| 1426 object, | 1451 object, |
| 1427 lookup, | 1452 lookup, |
| 1428 receiver(), this->name(), value(), scratch1(), scratch2(), | 1453 receiver(), this->name(), value(), scratch1(), scratch2(), |
| 1429 &miss); | 1454 &miss); |
| 1430 | 1455 |
| 1431 // Handle store cache miss. | 1456 // Handle store cache miss. |
| 1432 __ bind(&miss); | 1457 __ bind(&miss); |
| 1433 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1458 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1434 | 1459 |
| 1435 // Return the generated code. | 1460 // Return the generated code. |
| 1436 return GetCode(kind(), Code::FIELD, name); | 1461 return GetCode(kind(), Code::FAST, name); |
| 1437 } | 1462 } |
| 1438 | 1463 |
| 1439 | 1464 |
| 1440 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( | 1465 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( |
| 1441 Handle<JSObject> object, | 1466 Handle<JSObject> object, |
| 1442 Handle<JSObject> holder, | 1467 Handle<JSObject> holder, |
| 1443 Handle<Name> name, | 1468 Handle<Name> name, |
| 1444 Handle<JSFunction> setter) { | 1469 Handle<JSFunction> setter) { |
| 1445 Label success; | 1470 HandlerFrontend(object, receiver(), holder, name); |
| 1446 HandlerFrontend(object, receiver(), holder, name, &success); | |
| 1447 | |
| 1448 __ bind(&success); | |
| 1449 GenerateStoreViaSetter(masm(), setter); | 1471 GenerateStoreViaSetter(masm(), setter); |
| 1450 | 1472 |
| 1451 return GetCode(kind(), Code::CALLBACKS, name); | 1473 return GetCode(kind(), Code::FAST, name); |
| 1452 } | 1474 } |
| 1453 | 1475 |
| 1454 | 1476 |
| 1455 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 1477 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 1456 Handle<Map> receiver_map) { | 1478 Handle<Map> receiver_map) { |
| 1457 ElementsKind elements_kind = receiver_map->elements_kind(); | 1479 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1458 if (receiver_map->has_fast_elements() || | 1480 if (receiver_map->has_fast_elements() || |
| 1459 receiver_map->has_external_array_elements()) { | 1481 receiver_map->has_external_array_elements()) { |
| 1460 Handle<Code> stub = KeyedLoadFastElementStub( | 1482 Handle<Code> stub = KeyedLoadFastElementStub( |
| 1461 receiver_map->instance_type() == JS_ARRAY_TYPE, | 1483 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 1462 elements_kind).GetCode(isolate()); | 1484 elements_kind).GetCode(isolate()); |
| 1463 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | 1485 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); |
| 1464 } else { | 1486 } else { |
| 1465 Handle<Code> stub = | 1487 Handle<Code> stub = FLAG_compiled_keyed_dictionary_loads |
| 1466 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 1488 ? KeyedLoadDictionaryElementStub().GetCode(isolate()) |
| 1489 : KeyedLoadDictionaryElementPlatformStub().GetCode(isolate()); |
| 1467 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | 1490 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); |
| 1468 } | 1491 } |
| 1469 | 1492 |
| 1470 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss); | 1493 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss); |
| 1471 | 1494 |
| 1472 // Return the generated code. | 1495 // Return the generated code. |
| 1473 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); | 1496 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); |
| 1474 } | 1497 } |
| 1475 | 1498 |
| 1476 | 1499 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); | 1571 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); |
| 1549 JitEvent(name, code); | 1572 JitEvent(name, code); |
| 1550 return code; | 1573 return code; |
| 1551 } | 1574 } |
| 1552 | 1575 |
| 1553 | 1576 |
| 1554 Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, | 1577 Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, |
| 1555 Code::StubType type, | 1578 Code::StubType type, |
| 1556 Handle<Name> name) { | 1579 Handle<Name> name) { |
| 1557 Code::Flags flags = Code::ComputeFlags( | 1580 Code::Flags flags = Code::ComputeFlags( |
| 1558 Code::HANDLER, MONOMORPHIC, extra_state(), type, kind); | 1581 Code::HANDLER, MONOMORPHIC, extra_state(), type, kind, cache_holder_); |
| 1559 Handle<Code> code = GetCodeWithFlags(flags, name); | 1582 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1560 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); | 1583 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); |
| 1561 JitEvent(name, code); | 1584 JitEvent(name, code); |
| 1562 return code; | 1585 return code; |
| 1563 } | 1586 } |
| 1564 | 1587 |
| 1565 | 1588 |
| 1566 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, | 1589 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, |
| 1567 CodeHandleList* handlers) { | 1590 CodeHandleList* handlers) { |
| 1568 for (int i = 0; i < receiver_maps->length(); ++i) { | 1591 for (int i = 0; i < receiver_maps->length(); ++i) { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1716 holder, | 1739 holder, |
| 1717 cell, | 1740 cell, |
| 1718 function, | 1741 function, |
| 1719 fname); | 1742 fname); |
| 1720 } | 1743 } |
| 1721 | 1744 |
| 1722 | 1745 |
| 1723 Handle<Code> CallStubCompiler::GetCode(Code::StubType type, | 1746 Handle<Code> CallStubCompiler::GetCode(Code::StubType type, |
| 1724 Handle<Name> name) { | 1747 Handle<Name> name) { |
| 1725 int argc = arguments_.immediate(); | 1748 int argc = arguments_.immediate(); |
| 1726 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, | 1749 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 1727 extra_state_, | 1750 kind_, extra_state_, cache_holder_, type, argc); |
| 1728 type, | |
| 1729 argc, | |
| 1730 cache_holder_); | |
| 1731 return GetCodeWithFlags(flags, name); | 1751 return GetCodeWithFlags(flags, name); |
| 1732 } | 1752 } |
| 1733 | 1753 |
| 1734 | 1754 |
| 1735 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { | 1755 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { |
| 1736 Handle<String> function_name; | 1756 Handle<String> function_name; |
| 1737 if (function->shared()->name()->IsString()) { | 1757 if (function->shared()->name()->IsString()) { |
| 1738 function_name = Handle<String>(String::cast(function->shared()->name())); | 1758 function_name = Handle<String>(String::cast(function->shared()->name())); |
| 1739 } | 1759 } |
| 1740 return GetCode(Code::CONSTANT, function_name); | 1760 return GetCode(Code::FAST, function_name); |
| 1741 } | 1761 } |
| 1742 | 1762 |
| 1743 | 1763 |
| 1744 CallOptimization::CallOptimization(LookupResult* lookup) { | 1764 CallOptimization::CallOptimization(LookupResult* lookup) { |
| 1745 if (lookup->IsFound() && | 1765 if (lookup->IsFound() && |
| 1746 lookup->IsCacheable() && | 1766 lookup->IsCacheable() && |
| 1747 lookup->IsConstantFunction()) { | 1767 lookup->IsConstantFunction()) { |
| 1748 // We only optimize constant function calls. | 1768 // We only optimize constant function calls. |
| 1749 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); | 1769 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); |
| 1750 } else { | 1770 } else { |
| 1751 Initialize(Handle<JSFunction>::null()); | 1771 Initialize(Handle<JSFunction>::null()); |
| 1752 } | 1772 } |
| 1753 } | 1773 } |
| 1754 | 1774 |
| 1755 | 1775 |
| 1756 CallOptimization::CallOptimization(Handle<JSFunction> function) { | 1776 CallOptimization::CallOptimization(Handle<JSFunction> function) { |
| 1757 Initialize(function); | 1777 Initialize(function); |
| 1758 } | 1778 } |
| 1759 | 1779 |
| 1760 | 1780 |
| 1761 int CallOptimization::GetPrototypeDepthOfExpectedType( | 1781 int CallOptimization::GetPrototypeDepthOfExpectedType( |
| 1762 Handle<JSObject> object, | 1782 Handle<JSObject> object, |
| 1763 Handle<JSObject> holder) const { | 1783 Handle<JSObject> holder) const { |
| 1764 ASSERT(is_simple_api_call()); | 1784 ASSERT(is_simple_api_call()); |
| 1765 if (expected_receiver_type_.is_null()) return 0; | 1785 if (expected_receiver_type_.is_null()) return 0; |
| 1766 int depth = 0; | 1786 int depth = 0; |
| 1767 while (!object.is_identical_to(holder)) { | 1787 while (!object.is_identical_to(holder)) { |
| 1768 if (object->IsInstanceOf(*expected_receiver_type_)) return depth; | 1788 if (expected_receiver_type_->IsTemplateFor(object->map())) return depth; |
| 1769 object = Handle<JSObject>(JSObject::cast(object->GetPrototype())); | 1789 object = Handle<JSObject>(JSObject::cast(object->GetPrototype())); |
| 1770 if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth; | 1790 if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth; |
| 1771 ++depth; | 1791 ++depth; |
| 1772 } | 1792 } |
| 1773 if (holder->IsInstanceOf(*expected_receiver_type_)) return depth; | 1793 if (expected_receiver_type_->IsTemplateFor(holder->map())) return depth; |
| 1774 return kInvalidProtoDepth; | 1794 return kInvalidProtoDepth; |
| 1775 } | 1795 } |
| 1776 | 1796 |
| 1777 | 1797 |
| 1778 void CallOptimization::Initialize(Handle<JSFunction> function) { | 1798 void CallOptimization::Initialize(Handle<JSFunction> function) { |
| 1779 constant_function_ = Handle<JSFunction>::null(); | 1799 constant_function_ = Handle<JSFunction>::null(); |
| 1780 is_simple_api_call_ = false; | 1800 is_simple_api_call_ = false; |
| 1781 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); | 1801 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); |
| 1782 api_call_info_ = Handle<CallHandlerInfo>::null(); | 1802 api_call_info_ = Handle<CallHandlerInfo>::null(); |
| 1783 | 1803 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1808 Handle<FunctionTemplateInfo>( | 1828 Handle<FunctionTemplateInfo>( |
| 1809 FunctionTemplateInfo::cast(signature->receiver())); | 1829 FunctionTemplateInfo::cast(signature->receiver())); |
| 1810 } | 1830 } |
| 1811 } | 1831 } |
| 1812 | 1832 |
| 1813 is_simple_api_call_ = true; | 1833 is_simple_api_call_ = true; |
| 1814 } | 1834 } |
| 1815 | 1835 |
| 1816 | 1836 |
| 1817 } } // namespace v8::internal | 1837 } } // namespace v8::internal |
| OLD | NEW |