| 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 *secondary = *primary; | 102 *secondary = *primary; |
| 103 } | 103 } |
| 104 | 104 |
| 105 // Update primary cache. | 105 // Update primary cache. |
| 106 primary->key = name; | 106 primary->key = name; |
| 107 primary->value = code; | 107 primary->value = code; |
| 108 return code; | 108 return code; |
| 109 } | 109 } |
| 110 | 110 |
| 111 | 111 |
| 112 MaybeObject* StubCache::ComputeLoadNonexistent(String* name, | 112 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name, |
| 113 JSObject* receiver) { | 113 Handle<JSObject> receiver) { |
| 114 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties()); | 114 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties()); |
| 115 // If no global objects are present in the prototype chain, the load | 115 // If no global objects are present in the prototype chain, the load |
| 116 // nonexistent IC stub can be shared for all names for a given map | 116 // nonexistent IC stub can be shared for all names for a given map |
| 117 // and we use the empty string for the map cache in that case. If | 117 // and we use the empty string for the map cache in that case. If |
| 118 // there are global objects involved, we need to check global | 118 // there are global objects involved, we need to check global |
| 119 // property cells in the stub and therefore the stub will be | 119 // property cells in the stub and therefore the stub will be |
| 120 // specific to the name. | 120 // specific to the name. |
| 121 String* cache_name = heap()->empty_string(); | 121 Handle<String> cache_name = factory()->empty_string(); |
| 122 if (receiver->IsGlobalObject()) cache_name = name; | 122 if (receiver->IsGlobalObject()) cache_name = name; |
| 123 JSObject* last = receiver; | 123 Handle<JSObject> last = receiver; |
| 124 while (last->GetPrototype() != heap()->null_value()) { | 124 while (last->GetPrototype() != heap()->null_value()) { |
| 125 last = JSObject::cast(last->GetPrototype()); | 125 last = Handle<JSObject>(JSObject::cast(last->GetPrototype())); |
| 126 if (last->IsGlobalObject()) cache_name = name; | 126 if (last->IsGlobalObject()) cache_name = name; |
| 127 } | 127 } |
| 128 // Compile the stub that is either shared for all names or | 128 // Compile the stub that is either shared for all names or |
| 129 // name specific if there are global objects involved. | 129 // name specific if there are global objects involved. |
| 130 Code::Flags flags = | 130 Code::Flags flags = |
| 131 Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT); | 131 Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT); |
| 132 Object* code = receiver->map()->FindInCodeCache(cache_name, flags); | 132 Handle<Object> probe(receiver->map()->FindInCodeCache(*cache_name, flags)); |
| 133 if (code->IsUndefined()) { | 133 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 134 LoadStubCompiler compiler; | 134 |
| 135 { MaybeObject* maybe_code = | 135 LoadStubCompiler compiler(isolate_); |
| 136 compiler.CompileLoadNonexistent(cache_name, receiver, last); | 136 Handle<Code> code = |
| 137 if (!maybe_code->ToObject(&code)) return maybe_code; | 137 compiler.CompileLoadNonexistent(cache_name, receiver, last); |
| 138 } | 138 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name)); |
| 139 PROFILE(isolate_, | 139 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code)); |
| 140 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name)); | 140 JSObject::UpdateMapCodeCache(receiver, cache_name, code); |
| 141 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, cache_name, Code::cast(code))); | 141 return code; |
| 142 Object* result; | 142 } |
| 143 { MaybeObject* maybe_result = | 143 |
| 144 receiver->UpdateMapCodeCache(cache_name, Code::cast(code)); | 144 |
| 145 if (!maybe_result->ToObject(&result)) return maybe_result; | 145 Handle<Code> StubCache::ComputeLoadField(Handle<String> name, |
| 146 } | 146 Handle<JSObject> receiver, |
| 147 } | 147 Handle<JSObject> holder, |
| 148 return code; | |
| 149 } | |
| 150 | |
| 151 | |
| 152 MaybeObject* StubCache::ComputeLoadField(String* name, | |
| 153 JSObject* receiver, | |
| 154 JSObject* holder, | |
| 155 int field_index) { | 148 int field_index) { |
| 156 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | 149 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 157 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD); | 150 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD); |
| 158 Object* code = receiver->map()->FindInCodeCache(name, flags); | 151 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 159 if (code->IsUndefined()) { | 152 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 160 LoadStubCompiler compiler; | 153 |
| 161 { MaybeObject* maybe_code = | 154 LoadStubCompiler compiler(isolate_); |
| 162 compiler.CompileLoadField(receiver, holder, field_index, name); | 155 Handle<Code> code = |
| 163 if (!maybe_code->ToObject(&code)) return maybe_code; | 156 compiler.CompileLoadField(receiver, holder, field_index, name); |
| 164 } | 157 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
| 165 PROFILE(isolate_, | 158 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
| 166 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 159 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 167 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code))); | 160 return code; |
| 168 Object* result; | 161 } |
| 169 { MaybeObject* maybe_result = | 162 |
| 170 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 163 |
| 171 if (!maybe_result->ToObject(&result)) return maybe_result; | 164 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 172 } | 165 Handle<String> name, |
| 173 } | 166 Handle<JSObject> object, |
| 174 return code; | 167 Handle<JSObject> holder, |
| 175 } | 168 Handle<AccessorInfo> callback) { |
| 176 | 169 CALL_HEAP_FUNCTION(isolate(), |
| 177 | 170 (set_failure(NULL), |
| 178 MaybeObject* StubCache::ComputeLoadCallback(String* name, | 171 CompileLoadCallback(*name, *object, *holder, *callback)), |
| 179 JSObject* receiver, | 172 Code); |
| 180 JSObject* holder, | 173 } |
| 181 AccessorInfo* callback) { | 174 |
| 175 |
| 176 Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name, |
| 177 Handle<JSObject> receiver, |
| 178 Handle<JSObject> holder, |
| 179 Handle<AccessorInfo> callback) { |
| 182 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); | 180 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); |
| 183 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | 181 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 184 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS); | 182 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS); |
| 185 Object* code = receiver->map()->FindInCodeCache(name, flags); | 183 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 186 if (code->IsUndefined()) { | 184 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 187 LoadStubCompiler compiler; | 185 |
| 188 { MaybeObject* maybe_code = | 186 LoadStubCompiler compiler(isolate_); |
| 189 compiler.CompileLoadCallback(name, receiver, holder, callback); | 187 Handle<Code> code = |
| 190 if (!maybe_code->ToObject(&code)) return maybe_code; | 188 compiler.CompileLoadCallback(name, receiver, holder, callback); |
| 191 } | 189 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
| 192 PROFILE(isolate_, | 190 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
| 193 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 191 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 194 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code))); | 192 return code; |
| 195 Object* result; | 193 } |
| 196 { MaybeObject* maybe_result = | 194 |
| 197 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 195 |
| 198 if (!maybe_result->ToObject(&result)) return maybe_result; | 196 Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name, |
| 199 } | 197 Handle<JSObject> receiver, |
| 200 } | 198 Handle<JSObject> holder, |
| 201 return code; | 199 Handle<Object> value) { |
| 202 } | 200 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 203 | |
| 204 | |
| 205 MaybeObject* StubCache::ComputeLoadConstant(String* name, | |
| 206 JSObject* receiver, | |
| 207 JSObject* holder, | |
| 208 Object* value) { | |
| 209 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | |
| 210 Code::Flags flags = | 201 Code::Flags flags = |
| 211 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION); | 202 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION); |
| 212 Object* code = receiver->map()->FindInCodeCache(name, flags); | 203 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 213 if (code->IsUndefined()) { | 204 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 214 LoadStubCompiler compiler; | 205 |
| 215 { MaybeObject* maybe_code = | 206 LoadStubCompiler compiler(isolate_); |
| 216 compiler.CompileLoadConstant(receiver, holder, value, name); | 207 Handle<Code> code = |
| 217 if (!maybe_code->ToObject(&code)) return maybe_code; | 208 compiler.CompileLoadConstant(receiver, holder, value, name); |
| 218 } | 209 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
| 219 PROFILE(isolate_, | 210 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
| 220 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 211 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 221 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code))); | 212 return code; |
| 222 Object* result; | 213 } |
| 223 { MaybeObject* maybe_result = | 214 |
| 224 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 215 |
| 225 if (!maybe_result->ToObject(&result)) return maybe_result; | 216 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, |
| 226 } | 217 Handle<JSObject> holder, |
| 227 } | 218 Handle<String> name) { |
| 228 return code; | 219 CALL_HEAP_FUNCTION(isolate(), |
| 229 } | 220 (set_failure(NULL), |
| 230 | 221 CompileLoadInterceptor(*object, *holder, *name)), |
| 231 | 222 Code); |
| 232 MaybeObject* StubCache::ComputeLoadInterceptor(String* name, | 223 } |
| 233 JSObject* receiver, | 224 |
| 234 JSObject* holder) { | 225 |
| 235 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | 226 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name, |
| 227 Handle<JSObject> receiver, |
| 228 Handle<JSObject> holder) { |
| 229 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 236 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR); | 230 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR); |
| 237 Object* code = receiver->map()->FindInCodeCache(name, flags); | 231 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 238 if (code->IsUndefined()) { | 232 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 239 LoadStubCompiler compiler; | 233 |
| 240 { MaybeObject* maybe_code = | 234 LoadStubCompiler compiler(isolate_); |
| 241 compiler.CompileLoadInterceptor(receiver, holder, name); | 235 Handle<Code> code = |
| 242 if (!maybe_code->ToObject(&code)) return maybe_code; | 236 compiler.CompileLoadInterceptor(receiver, holder, name); |
| 243 } | 237 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
| 244 PROFILE(isolate_, | 238 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
| 245 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 239 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 246 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code))); | 240 return code; |
| 247 Object* result; | 241 } |
| 248 { MaybeObject* maybe_result = | 242 |
| 249 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 243 |
| 250 if (!maybe_result->ToObject(&result)) return maybe_result; | 244 Handle<Code> StubCache::ComputeLoadNormal() { |
| 251 } | 245 return isolate_->builtins()->LoadIC_Normal(); |
| 252 } | 246 } |
| 253 return code; | 247 |
| 254 } | 248 |
| 255 | 249 Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name, |
| 256 | 250 Handle<JSObject> receiver, |
| 257 MaybeObject* StubCache::ComputeLoadNormal() { | 251 Handle<GlobalObject> holder, |
| 258 return isolate_->builtins()->builtin(Builtins::kLoadIC_Normal); | 252 Handle<JSGlobalPropertyCell> cell, |
| 259 } | |
| 260 | |
| 261 | |
| 262 MaybeObject* StubCache::ComputeLoadGlobal(String* name, | |
| 263 JSObject* receiver, | |
| 264 GlobalObject* holder, | |
| 265 JSGlobalPropertyCell* cell, | |
| 266 bool is_dont_delete) { | 253 bool is_dont_delete) { |
| 267 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | 254 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 268 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); | 255 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); |
| 269 Object* code = receiver->map()->FindInCodeCache(name, flags); | 256 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 270 if (code->IsUndefined()) { | 257 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 271 LoadStubCompiler compiler; | 258 |
| 272 { MaybeObject* maybe_code = compiler.CompileLoadGlobal(receiver, | 259 LoadStubCompiler compiler(isolate_); |
| 273 holder, | 260 Handle<Code> code = |
| 274 cell, | 261 compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete); |
| 275 name, | 262 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
| 276 is_dont_delete); | 263 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
| 277 if (!maybe_code->ToObject(&code)) return maybe_code; | 264 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 278 } | 265 return code; |
| 279 PROFILE(isolate_, | 266 } |
| 280 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 267 |
| 281 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code))); | 268 |
| 282 Object* result; | 269 Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name, |
| 283 { MaybeObject* maybe_result = | 270 Handle<JSObject> receiver, |
| 284 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 271 Handle<JSObject> holder, |
| 285 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 286 } | |
| 287 } | |
| 288 return code; | |
| 289 } | |
| 290 | |
| 291 | |
| 292 MaybeObject* StubCache::ComputeKeyedLoadField(String* name, | |
| 293 JSObject* receiver, | |
| 294 JSObject* holder, | |
| 295 int field_index) { | 272 int field_index) { |
| 296 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | 273 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 297 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD); | 274 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD); |
| 298 Object* code = receiver->map()->FindInCodeCache(name, flags); | 275 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 299 if (code->IsUndefined()) { | 276 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 300 KeyedLoadStubCompiler compiler; | 277 |
| 301 { MaybeObject* maybe_code = | 278 KeyedLoadStubCompiler compiler(isolate_); |
| 302 compiler.CompileLoadField(name, receiver, holder, field_index); | 279 Handle<Code> code = |
| 303 if (!maybe_code->ToObject(&code)) return maybe_code; | 280 compiler.CompileLoadField(name, receiver, holder, field_index); |
| 304 } | 281 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 305 PROFILE(isolate_, | 282 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 306 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 283 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 307 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code))); | 284 return code; |
| 308 Object* result; | 285 } |
| 309 { MaybeObject* maybe_result = | 286 |
| 310 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 287 |
| 311 if (!maybe_result->ToObject(&result)) return maybe_result; | 288 Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name, |
| 312 } | 289 Handle<JSObject> receiver, |
| 313 } | 290 Handle<JSObject> holder, |
| 314 return code; | 291 Handle<Object> value) { |
| 315 } | 292 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 316 | |
| 317 | |
| 318 MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name, | |
| 319 JSObject* receiver, | |
| 320 JSObject* holder, | |
| 321 Object* value) { | |
| 322 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | |
| 323 Code::Flags flags = | 293 Code::Flags flags = |
| 324 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION); | 294 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION); |
| 325 Object* code = receiver->map()->FindInCodeCache(name, flags); | 295 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 326 if (code->IsUndefined()) { | 296 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 327 KeyedLoadStubCompiler compiler; | 297 |
| 328 { MaybeObject* maybe_code = | 298 KeyedLoadStubCompiler compiler(isolate_); |
| 329 compiler.CompileLoadConstant(name, receiver, holder, value); | 299 Handle<Code> code = |
| 330 if (!maybe_code->ToObject(&code)) return maybe_code; | 300 compiler.CompileLoadConstant(name, receiver, holder, value); |
| 331 } | 301 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 332 PROFILE(isolate_, | 302 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 333 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 303 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 334 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code))); | 304 return code; |
| 335 Object* result; | 305 } |
| 336 { MaybeObject* maybe_result = | 306 |
| 337 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 307 |
| 338 if (!maybe_result->ToObject(&result)) return maybe_result; | 308 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
| 339 } | 309 Handle<JSObject> object, |
| 340 } | 310 Handle<JSObject> holder, |
| 341 return code; | 311 Handle<String> name) { |
| 342 } | 312 CALL_HEAP_FUNCTION(isolate(), |
| 343 | 313 (set_failure(NULL), |
| 344 | 314 CompileLoadInterceptor(*object, *holder, *name)), |
| 345 MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name, | 315 Code); |
| 346 JSObject* receiver, | 316 } |
| 347 JSObject* holder) { | 317 |
| 348 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | 318 |
| 319 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name, |
| 320 Handle<JSObject> receiver, |
| 321 Handle<JSObject> holder) { |
| 322 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 349 Code::Flags flags = | 323 Code::Flags flags = |
| 350 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR); | 324 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR); |
| 351 Object* code = receiver->map()->FindInCodeCache(name, flags); | 325 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 352 if (code->IsUndefined()) { | 326 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 353 KeyedLoadStubCompiler compiler; | 327 |
| 354 { MaybeObject* maybe_code = | 328 KeyedLoadStubCompiler compiler(isolate_); |
| 355 compiler.CompileLoadInterceptor(receiver, holder, name); | 329 Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name); |
| 356 if (!maybe_code->ToObject(&code)) return maybe_code; | 330 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 357 } | 331 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 358 PROFILE(isolate_, | 332 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 359 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 333 return code; |
| 360 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code))); | 334 } |
| 361 Object* result; | 335 |
| 362 { MaybeObject* maybe_result = | 336 |
| 363 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 337 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
| 364 if (!maybe_result->ToObject(&result)) return maybe_result; | 338 Handle<String> name, |
| 365 } | 339 Handle<JSObject> object, |
| 366 } | 340 Handle<JSObject> holder, |
| 367 return code; | 341 Handle<AccessorInfo> callback) { |
| 368 } | 342 CALL_HEAP_FUNCTION(isolate(), |
| 369 | 343 (set_failure(NULL), |
| 370 | 344 CompileLoadCallback(*name, *object, *holder, *callback)), |
| 371 MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name, | 345 Code); |
| 372 JSObject* receiver, | 346 } |
| 373 JSObject* holder, | 347 |
| 374 AccessorInfo* callback) { | 348 |
| 375 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); | 349 Handle<Code> StubCache::ComputeKeyedLoadCallback( |
| 350 Handle<String> name, |
| 351 Handle<JSObject> receiver, |
| 352 Handle<JSObject> holder, |
| 353 Handle<AccessorInfo> callback) { |
| 354 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
| 376 Code::Flags flags = | 355 Code::Flags flags = |
| 377 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 356 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
| 378 Object* code = receiver->map()->FindInCodeCache(name, flags); | 357 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 379 if (code->IsUndefined()) { | 358 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 380 KeyedLoadStubCompiler compiler; | 359 |
| 381 { MaybeObject* maybe_code = | 360 KeyedLoadStubCompiler compiler(isolate_); |
| 382 compiler.CompileLoadCallback(name, receiver, holder, callback); | 361 Handle<Code> code = |
| 383 if (!maybe_code->ToObject(&code)) return maybe_code; | 362 compiler.CompileLoadCallback(name, receiver, holder, callback); |
| 384 } | 363 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 385 PROFILE(isolate_, | 364 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 386 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 365 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 387 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code))); | 366 return code; |
| 388 Object* result; | 367 } |
| 389 { MaybeObject* maybe_result = | 368 |
| 390 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 369 |
| 391 if (!maybe_result->ToObject(&result)) return maybe_result; | 370 Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name, |
| 392 } | 371 Handle<JSArray> receiver) { |
| 393 } | |
| 394 return code; | |
| 395 } | |
| 396 | |
| 397 | |
| 398 | |
| 399 MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name, | |
| 400 JSArray* receiver) { | |
| 401 Code::Flags flags = | 372 Code::Flags flags = |
| 402 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 373 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
| 403 ASSERT(receiver->IsJSObject()); | 374 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 404 Object* code = receiver->map()->FindInCodeCache(name, flags); | 375 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 405 if (code->IsUndefined()) { | 376 |
| 406 KeyedLoadStubCompiler compiler; | 377 KeyedLoadStubCompiler compiler(isolate_); |
| 407 { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name); | 378 Handle<Code> code = compiler.CompileLoadArrayLength(name); |
| 408 if (!maybe_code->ToObject(&code)) return maybe_code; | 379 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 409 } | 380 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 410 PROFILE(isolate_, | 381 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 411 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 382 return code; |
| 412 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code))); | 383 } |
| 413 Object* result; | 384 |
| 414 { MaybeObject* maybe_result = | 385 |
| 415 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 386 Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name, |
| 416 if (!maybe_result->ToObject(&result)) return maybe_result; | 387 Handle<String> receiver) { |
| 417 } | |
| 418 } | |
| 419 return code; | |
| 420 } | |
| 421 | |
| 422 | |
| 423 MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name, | |
| 424 String* receiver) { | |
| 425 Code::Flags flags = | 388 Code::Flags flags = |
| 426 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 389 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
| 427 Map* map = receiver->map(); | 390 Handle<Map> map(receiver->map()); |
| 428 Object* code = map->FindInCodeCache(name, flags); | 391 Handle<Object> probe(map->FindInCodeCache(*name, flags)); |
| 429 if (code->IsUndefined()) { | 392 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 430 KeyedLoadStubCompiler compiler; | 393 |
| 431 { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name); | 394 KeyedLoadStubCompiler compiler(isolate_); |
| 432 if (!maybe_code->ToObject(&code)) return maybe_code; | 395 Handle<Code> code = compiler.CompileLoadStringLength(name); |
| 433 } | 396 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 434 PROFILE(isolate_, | 397 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 435 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 398 Map::UpdateCodeCache(map, name, code); |
| 436 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code))); | 399 return code; |
| 437 Object* result; | 400 } |
| 438 { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code)); | 401 |
| 439 if (!maybe_result->ToObject(&result)) return maybe_result; | 402 |
| 440 } | 403 Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype( |
| 441 } | 404 Handle<String> name, |
| 442 return code; | 405 Handle<JSFunction> receiver) { |
| 443 } | |
| 444 | |
| 445 | |
| 446 MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype( | |
| 447 String* name, | |
| 448 JSFunction* receiver) { | |
| 449 Code::Flags flags = | 406 Code::Flags flags = |
| 450 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 407 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
| 451 Object* code = receiver->map()->FindInCodeCache(name, flags); | 408 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 452 if (code->IsUndefined()) { | 409 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 453 KeyedLoadStubCompiler compiler; | 410 |
| 454 { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name); | 411 KeyedLoadStubCompiler compiler(isolate_); |
| 455 if (!maybe_code->ToObject(&code)) return maybe_code; | 412 Handle<Code> code = compiler.CompileLoadFunctionPrototype(name); |
| 456 } | 413 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 457 PROFILE(isolate_, | 414 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 458 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 415 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 459 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code))); | 416 return code; |
| 460 Object* result; | 417 } |
| 461 { MaybeObject* maybe_result = | 418 |
| 462 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 419 |
| 463 if (!maybe_result->ToObject(&result)) return maybe_result; | 420 Handle<Code> StubCache::ComputeStoreField(Handle<String> name, |
| 464 } | 421 Handle<JSObject> receiver, |
| 465 } | |
| 466 return code; | |
| 467 } | |
| 468 | |
| 469 | |
| 470 MaybeObject* StubCache::ComputeStoreField(String* name, | |
| 471 JSObject* receiver, | |
| 472 int field_index, | 422 int field_index, |
| 473 Map* transition, | 423 Handle<Map> transition, |
| 474 StrictModeFlag strict_mode) { | 424 StrictModeFlag strict_mode) { |
| 475 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION; | 425 PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION; |
| 476 Code::Flags flags = Code::ComputeMonomorphicFlags( | 426 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 477 Code::STORE_IC, type, strict_mode); | 427 Code::STORE_IC, type, strict_mode); |
| 478 Object* code = receiver->map()->FindInCodeCache(name, flags); | 428 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 479 if (code->IsUndefined()) { | 429 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 480 StoreStubCompiler compiler(strict_mode); | 430 |
| 481 { MaybeObject* maybe_code = | 431 StoreStubCompiler compiler(isolate_, strict_mode); |
| 482 compiler.CompileStoreField(receiver, field_index, transition, name); | 432 Handle<Code> code = |
| 483 if (!maybe_code->ToObject(&code)) return maybe_code; | 433 compiler.CompileStoreField(receiver, field_index, transition, name); |
| 484 } | 434 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
| 485 PROFILE(isolate_, | 435 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
| 486 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); | 436 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 487 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code))); | 437 return code; |
| 488 Object* result; | 438 } |
| 489 { MaybeObject* maybe_result = | 439 |
| 490 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 440 |
| 491 if (!maybe_result->ToObject(&result)) return maybe_result; | 441 Handle<Code> StubCache::ComputeKeyedLoadOrStoreElement( |
| 492 } | 442 Handle<JSObject> receiver, |
| 493 } | |
| 494 return code; | |
| 495 } | |
| 496 | |
| 497 | |
| 498 MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement( | |
| 499 JSObject* receiver, | |
| 500 KeyedIC::StubKind stub_kind, | 443 KeyedIC::StubKind stub_kind, |
| 501 StrictModeFlag strict_mode) { | 444 StrictModeFlag strict_mode) { |
| 502 Code::Flags flags = | 445 Code::Flags flags = |
| 503 Code::ComputeMonomorphicFlags( | 446 Code::ComputeMonomorphicFlags( |
| 504 stub_kind == KeyedIC::LOAD ? Code::KEYED_LOAD_IC | 447 stub_kind == KeyedIC::LOAD ? Code::KEYED_LOAD_IC |
| 505 : Code::KEYED_STORE_IC, | 448 : Code::KEYED_STORE_IC, |
| 506 NORMAL, | 449 NORMAL, |
| 507 strict_mode); | 450 strict_mode); |
| 508 String* name = NULL; | 451 Handle<String> name; |
| 509 switch (stub_kind) { | 452 switch (stub_kind) { |
| 510 case KeyedIC::LOAD: | 453 case KeyedIC::LOAD: |
| 511 name = isolate()->heap()->KeyedLoadElementMonomorphic_symbol(); | 454 name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol(); |
| 512 break; | 455 break; |
| 513 case KeyedIC::STORE_NO_TRANSITION: | 456 case KeyedIC::STORE_NO_TRANSITION: |
| 514 name = isolate()->heap()->KeyedStoreElementMonomorphic_symbol(); | 457 name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol(); |
| 515 break; | 458 break; |
| 516 default: | 459 default: |
| 517 UNREACHABLE(); | 460 UNREACHABLE(); |
| 518 break; | 461 break; |
| 519 } | 462 } |
| 520 Object* maybe_code = receiver->map()->FindInCodeCache(name, flags); | 463 Handle<Map> receiver_map(receiver->map()); |
| 521 if (!maybe_code->IsUndefined()) return Code::cast(maybe_code); | 464 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags)); |
| 465 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 522 | 466 |
| 523 Map* receiver_map = receiver->map(); | 467 Handle<Code> code; |
| 524 MaybeObject* maybe_new_code = NULL; | |
| 525 switch (stub_kind) { | 468 switch (stub_kind) { |
| 526 case KeyedIC::LOAD: { | 469 case KeyedIC::LOAD: { |
| 527 KeyedLoadStubCompiler compiler; | 470 KeyedLoadStubCompiler compiler(isolate_); |
| 528 maybe_new_code = compiler.CompileLoadElement(receiver_map); | 471 code = compiler.CompileLoadElement(receiver_map); |
| 529 break; | 472 break; |
| 530 } | 473 } |
| 531 case KeyedIC::STORE_NO_TRANSITION: { | 474 case KeyedIC::STORE_NO_TRANSITION: { |
| 532 KeyedStoreStubCompiler compiler(strict_mode); | 475 KeyedStoreStubCompiler compiler(isolate_, strict_mode); |
| 533 maybe_new_code = compiler.CompileStoreElement(receiver_map); | 476 code = compiler.CompileStoreElement(receiver_map); |
| 534 break; | 477 break; |
| 535 } | 478 } |
| 536 default: | 479 default: |
| 537 UNREACHABLE(); | 480 UNREACHABLE(); |
| 538 break; | 481 break; |
| 539 } | 482 } |
| 540 Code* code = NULL; | 483 |
| 541 if (!maybe_new_code->To(&code)) return maybe_new_code; | 484 ASSERT(!code.is_null()); |
| 542 | 485 |
| 543 if (stub_kind == KeyedIC::LOAD) { | 486 if (stub_kind == KeyedIC::LOAD) { |
| 544 PROFILE(isolate_, | 487 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0)); |
| 545 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, | |
| 546 Code::cast(code), 0)); | |
| 547 } else { | 488 } else { |
| 548 PROFILE(isolate_, | 489 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0)); |
| 549 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, | |
| 550 Code::cast(code), 0)); | |
| 551 } | 490 } |
| 552 ASSERT(code->IsCode()); | 491 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 553 Object* result; | |
| 554 { MaybeObject* maybe_result = | |
| 555 receiver->UpdateMapCodeCache(name, Code::cast(code)); | |
| 556 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 557 } | |
| 558 return code; | 492 return code; |
| 559 } | 493 } |
| 560 | 494 |
| 561 | 495 |
| 562 MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { | 496 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { |
| 563 return isolate_->builtins()->builtin((strict_mode == kStrictMode) | 497 return (strict_mode == kStrictMode) |
| 564 ? Builtins::kStoreIC_Normal_Strict | 498 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict() |
| 565 : Builtins::kStoreIC_Normal); | 499 : isolate_->builtins()->Builtins::StoreIC_Normal(); |
| 566 } | 500 } |
| 567 | 501 |
| 568 | 502 |
| 569 MaybeObject* StubCache::ComputeStoreGlobal(String* name, | 503 Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name, |
| 570 GlobalObject* receiver, | 504 Handle<GlobalObject> receiver, |
| 571 JSGlobalPropertyCell* cell, | 505 Handle<JSGlobalPropertyCell> cell, |
| 572 StrictModeFlag strict_mode) { | 506 StrictModeFlag strict_mode) { |
| 573 Code::Flags flags = Code::ComputeMonomorphicFlags( | 507 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 574 Code::STORE_IC, NORMAL, strict_mode); | 508 Code::STORE_IC, NORMAL, strict_mode); |
| 575 Object* code = receiver->map()->FindInCodeCache(name, flags); | 509 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 576 if (code->IsUndefined()) { | 510 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 577 StoreStubCompiler compiler(strict_mode); | 511 |
| 578 { MaybeObject* maybe_code = | 512 StoreStubCompiler compiler(isolate_, strict_mode); |
| 579 compiler.CompileStoreGlobal(receiver, cell, name); | 513 Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name); |
| 580 if (!maybe_code->ToObject(&code)) return maybe_code; | 514 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
| 581 } | 515 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
| 582 PROFILE(isolate_, | 516 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 583 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); | |
| 584 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code))); | |
| 585 Object* result; | |
| 586 { MaybeObject* maybe_result = | |
| 587 receiver->UpdateMapCodeCache(name, Code::cast(code)); | |
| 588 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 589 } | |
| 590 } | |
| 591 return code; | 517 return code; |
| 592 } | 518 } |
| 593 | 519 |
| 594 | 520 |
| 595 MaybeObject* StubCache::ComputeStoreCallback( | 521 Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name, |
| 596 String* name, | 522 Handle<JSObject> receiver, |
| 597 JSObject* receiver, | 523 Handle<AccessorInfo> callback, |
| 598 AccessorInfo* callback, | 524 StrictModeFlag strict_mode) { |
| 599 StrictModeFlag strict_mode) { | |
| 600 ASSERT(v8::ToCData<Address>(callback->setter()) != 0); | 525 ASSERT(v8::ToCData<Address>(callback->setter()) != 0); |
| 601 Code::Flags flags = Code::ComputeMonomorphicFlags( | 526 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 602 Code::STORE_IC, CALLBACKS, strict_mode); | 527 Code::STORE_IC, CALLBACKS, strict_mode); |
| 603 Object* code = receiver->map()->FindInCodeCache(name, flags); | 528 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 604 if (code->IsUndefined()) { | 529 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 605 StoreStubCompiler compiler(strict_mode); | 530 |
| 606 { MaybeObject* maybe_code = | 531 StoreStubCompiler compiler(isolate_, strict_mode); |
| 607 compiler.CompileStoreCallback(receiver, callback, name); | 532 Handle<Code> code = compiler.CompileStoreCallback(receiver, callback, name); |
| 608 if (!maybe_code->ToObject(&code)) return maybe_code; | 533 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
| 609 } | 534 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
| 610 PROFILE(isolate_, | 535 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 611 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); | |
| 612 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code))); | |
| 613 Object* result; | |
| 614 { MaybeObject* maybe_result = | |
| 615 receiver->UpdateMapCodeCache(name, Code::cast(code)); | |
| 616 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 617 } | |
| 618 } | |
| 619 return code; | 536 return code; |
| 620 } | 537 } |
| 621 | 538 |
| 622 | 539 |
| 623 MaybeObject* StubCache::ComputeStoreInterceptor( | 540 Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name, |
| 624 String* name, | 541 Handle<JSObject> receiver, |
| 625 JSObject* receiver, | 542 StrictModeFlag strict_mode) { |
| 626 StrictModeFlag strict_mode) { | |
| 627 Code::Flags flags = Code::ComputeMonomorphicFlags( | 543 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 628 Code::STORE_IC, INTERCEPTOR, strict_mode); | 544 Code::STORE_IC, INTERCEPTOR, strict_mode); |
| 629 Object* code = receiver->map()->FindInCodeCache(name, flags); | 545 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 630 if (code->IsUndefined()) { | 546 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 631 StoreStubCompiler compiler(strict_mode); | 547 |
| 632 { MaybeObject* maybe_code = | 548 StoreStubCompiler compiler(isolate_, strict_mode); |
| 633 compiler.CompileStoreInterceptor(receiver, name); | 549 Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name); |
| 634 if (!maybe_code->ToObject(&code)) return maybe_code; | 550 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
| 635 } | 551 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
| 636 PROFILE(isolate_, | 552 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 637 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); | 553 return code; |
| 638 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code))); | 554 } |
| 639 Object* result; | 555 |
| 640 { MaybeObject* maybe_result = | 556 Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name, |
| 641 receiver->UpdateMapCodeCache(name, Code::cast(code)); | 557 Handle<JSObject> receiver, |
| 642 if (!maybe_result->ToObject(&result)) return maybe_result; | 558 int field_index, |
| 643 } | 559 Handle<Map> transition, |
| 644 } | 560 StrictModeFlag strict_mode) { |
| 561 PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION; |
| 562 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 563 Code::KEYED_STORE_IC, type, strict_mode); |
| 564 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
| 565 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 566 |
| 567 KeyedStoreStubCompiler compiler(isolate(), strict_mode); |
| 568 Handle<Code> code = |
| 569 compiler.CompileStoreField(receiver, field_index, transition, name); |
| 570 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); |
| 571 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); |
| 572 JSObject::UpdateMapCodeCache(receiver, name, code); |
| 645 return code; | 573 return code; |
| 646 } | 574 } |
| 647 | 575 |
| 648 | 576 |
| 649 MaybeObject* StubCache::ComputeKeyedStoreField(String* name, | |
| 650 JSObject* receiver, | |
| 651 int field_index, | |
| 652 Map* transition, | |
| 653 StrictModeFlag strict_mode) { | |
| 654 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION; | |
| 655 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
| 656 Code::KEYED_STORE_IC, type, strict_mode); | |
| 657 Object* code = receiver->map()->FindInCodeCache(name, flags); | |
| 658 if (code->IsUndefined()) { | |
| 659 KeyedStoreStubCompiler compiler(strict_mode); | |
| 660 { MaybeObject* maybe_code = | |
| 661 compiler.CompileStoreField(receiver, field_index, transition, name); | |
| 662 if (!maybe_code->ToObject(&code)) return maybe_code; | |
| 663 } | |
| 664 PROFILE(isolate(), | |
| 665 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, | |
| 666 Code::cast(code), name)); | |
| 667 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, name, Code::cast(code))); | |
| 668 Object* result; | |
| 669 { MaybeObject* maybe_result = | |
| 670 receiver->UpdateMapCodeCache(name, Code::cast(code)); | |
| 671 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 672 } | |
| 673 } | |
| 674 return code; | |
| 675 } | |
| 676 | |
| 677 #define CALL_LOGGER_TAG(kind, type) \ | 577 #define CALL_LOGGER_TAG(kind, type) \ |
| 678 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | 578 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
| 679 | 579 |
| 680 MaybeObject* StubCache::ComputeCallConstant(int argc, | 580 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, |
| 581 Handle<JSObject> holder, |
| 582 Handle<JSFunction> function, |
| 583 Handle<String> name, |
| 584 CheckType check) { |
| 585 CALL_HEAP_FUNCTION( |
| 586 isolate(), |
| 587 (set_failure(NULL), |
| 588 CompileCallConstant(*object, *holder, *function, *name, check)), |
| 589 Code); |
| 590 } |
| 591 |
| 592 |
| 593 Handle<Code> StubCache::ComputeCallConstant(int argc, |
| 681 Code::Kind kind, | 594 Code::Kind kind, |
| 682 Code::ExtraICState extra_ic_state, | 595 Code::ExtraICState extra_state, |
| 683 String* name, | 596 Handle<String> name, |
| 684 Object* object, | 597 Handle<Object> object, |
| 685 JSObject* holder, | 598 Handle<JSObject> holder, |
| 686 JSFunction* function) { | 599 Handle<JSFunction> function) { |
| 687 // Compute the check type and the map. | 600 // Compute the check type and the map. |
| 688 InlineCacheHolderFlag cache_holder = | 601 InlineCacheHolderFlag cache_holder = |
| 689 IC::GetCodeCacheForObject(object, holder); | 602 IC::GetCodeCacheForObject(*object, *holder); |
| 690 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder); | 603 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder)); |
| 691 | 604 |
| 692 // Compute check type based on receiver/holder. | 605 // Compute check type based on receiver/holder. |
| 693 CheckType check = RECEIVER_MAP_CHECK; | 606 CheckType check = RECEIVER_MAP_CHECK; |
| 694 if (object->IsString()) { | 607 if (object->IsString()) { |
| 695 check = STRING_CHECK; | 608 check = STRING_CHECK; |
| 696 } else if (object->IsNumber()) { | 609 } else if (object->IsNumber()) { |
| 697 check = NUMBER_CHECK; | 610 check = NUMBER_CHECK; |
| 698 } else if (object->IsBoolean()) { | 611 } else if (object->IsBoolean()) { |
| 699 check = BOOLEAN_CHECK; | 612 check = BOOLEAN_CHECK; |
| 700 } | 613 } |
| 701 | 614 |
| 702 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 615 Code::Flags flags = |
| 703 CONSTANT_FUNCTION, | 616 Code::ComputeMonomorphicFlags(kind, CONSTANT_FUNCTION, extra_state, |
| 704 extra_ic_state, | 617 cache_holder, argc); |
| 705 cache_holder, | 618 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags)); |
| 706 argc); | 619 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 707 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 620 |
| 708 if (code->IsUndefined()) { | 621 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); |
| 709 // If the function hasn't been compiled yet, we cannot do it now | 622 Handle<Code> code = |
| 710 // because it may cause GC. To avoid this issue, we return an | 623 compiler.CompileCallConstant(object, holder, function, name, check); |
| 711 // internal error which will make sure we do not update any | 624 code->set_check_type(check); |
| 712 // caches. | 625 ASSERT_EQ(flags, code->flags()); |
| 713 if (!function->is_compiled()) return Failure::InternalError(); | 626 PROFILE(isolate_, |
| 714 // Compile the stub - only create stubs for fully compiled functions. | 627 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 715 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); | 628 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 716 { MaybeObject* maybe_code = | 629 JSObject::UpdateMapCodeCache(map_holder, name, code); |
| 717 compiler.CompileCallConstant(object, holder, function, name, check); | |
| 718 if (!maybe_code->ToObject(&code)) return maybe_code; | |
| 719 } | |
| 720 Code::cast(code)->set_check_type(check); | |
| 721 ASSERT_EQ(flags, Code::cast(code)->flags()); | |
| 722 PROFILE(isolate_, | |
| 723 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | |
| 724 Code::cast(code), name)); | |
| 725 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); | |
| 726 Object* result; | |
| 727 { MaybeObject* maybe_result = | |
| 728 map_holder->UpdateMapCodeCache(name, Code::cast(code)); | |
| 729 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 730 } | |
| 731 } | |
| 732 return code; | 630 return code; |
| 733 } | 631 } |
| 734 | 632 |
| 735 | 633 |
| 736 MaybeObject* StubCache::ComputeCallField(int argc, | 634 Handle<Code> StubCache::ComputeCallField(int argc, |
| 737 Code::Kind kind, | 635 Code::Kind kind, |
| 738 Code::ExtraICState extra_ic_state, | 636 Code::ExtraICState extra_state, |
| 739 String* name, | 637 Handle<String> name, |
| 740 Object* object, | 638 Handle<Object> object, |
| 741 JSObject* holder, | 639 Handle<JSObject> holder, |
| 742 int index) { | 640 int index) { |
| 743 // Compute the check type and the map. | 641 // Compute the check type and the map. |
| 744 InlineCacheHolderFlag cache_holder = | 642 InlineCacheHolderFlag cache_holder = |
| 745 IC::GetCodeCacheForObject(object, holder); | 643 IC::GetCodeCacheForObject(*object, *holder); |
| 746 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder); | 644 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder)); |
| 747 | 645 |
| 748 // TODO(1233596): We cannot do receiver map check for non-JS objects | 646 // TODO(1233596): We cannot do receiver map check for non-JS objects |
| 749 // because they may be represented as immediates without a | 647 // because they may be represented as immediates without a |
| 750 // map. Instead, we check against the map in the holder. | 648 // map. Instead, we check against the map in the holder. |
| 751 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 649 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
| 752 object = holder; | 650 object = holder; |
| 753 } | 651 } |
| 754 | 652 |
| 755 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 653 Code::Flags flags = |
| 756 FIELD, | 654 Code::ComputeMonomorphicFlags(kind, FIELD, extra_state, |
| 757 extra_ic_state, | 655 cache_holder, argc); |
| 758 cache_holder, | 656 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags)); |
| 759 argc); | 657 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 760 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 658 |
| 761 if (code->IsUndefined()) { | 659 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); |
| 762 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); | 660 Handle<Code> code = |
| 763 { MaybeObject* maybe_code = | 661 compiler.CompileCallField(Handle<JSObject>::cast(object), |
| 764 compiler.CompileCallField(JSObject::cast(object), | 662 holder, index, name); |
| 765 holder, | 663 ASSERT_EQ(flags, code->flags()); |
| 766 index, | 664 PROFILE(isolate_, |
| 767 name); | 665 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 768 if (!maybe_code->ToObject(&code)) return maybe_code; | 666 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 769 } | 667 JSObject::UpdateMapCodeCache(map_holder, name, code); |
| 770 ASSERT_EQ(flags, Code::cast(code)->flags()); | |
| 771 PROFILE(isolate_, | |
| 772 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | |
| 773 Code::cast(code), name)); | |
| 774 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); | |
| 775 Object* result; | |
| 776 { MaybeObject* maybe_result = | |
| 777 map_holder->UpdateMapCodeCache(name, Code::cast(code)); | |
| 778 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 779 } | |
| 780 } | |
| 781 return code; | 668 return code; |
| 782 } | 669 } |
| 783 | 670 |
| 784 | 671 |
| 785 MaybeObject* StubCache::ComputeCallInterceptor( | 672 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 786 int argc, | 673 Handle<JSObject> holder, |
| 787 Code::Kind kind, | 674 Handle<String> name) { |
| 788 Code::ExtraICState extra_ic_state, | 675 CALL_HEAP_FUNCTION( |
| 789 String* name, | 676 isolate(), |
| 790 Object* object, | 677 (set_failure(NULL), CompileCallInterceptor(*object, *holder, *name)), |
| 791 JSObject* holder) { | 678 Code); |
| 679 } |
| 680 |
| 681 |
| 682 Handle<Code> StubCache::ComputeCallInterceptor(int argc, |
| 683 Code::Kind kind, |
| 684 Code::ExtraICState extra_state, |
| 685 Handle<String> name, |
| 686 Handle<Object> object, |
| 687 Handle<JSObject> holder) { |
| 792 // Compute the check type and the map. | 688 // Compute the check type and the map. |
| 793 InlineCacheHolderFlag cache_holder = | 689 InlineCacheHolderFlag cache_holder = |
| 794 IC::GetCodeCacheForObject(object, holder); | 690 IC::GetCodeCacheForObject(*object, *holder); |
| 795 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder); | 691 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder)); |
| 796 | 692 |
| 797 // TODO(1233596): We cannot do receiver map check for non-JS objects | 693 // TODO(1233596): We cannot do receiver map check for non-JS objects |
| 798 // because they may be represented as immediates without a | 694 // because they may be represented as immediates without a |
| 799 // map. Instead, we check against the map in the holder. | 695 // map. Instead, we check against the map in the holder. |
| 800 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 696 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
| 801 object = holder; | 697 object = holder; |
| 802 } | 698 } |
| 803 | 699 |
| 804 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 700 Code::Flags flags = |
| 805 INTERCEPTOR, | 701 Code::ComputeMonomorphicFlags(kind, INTERCEPTOR, extra_state, |
| 806 extra_ic_state, | 702 cache_holder, argc); |
| 807 cache_holder, | 703 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags)); |
| 808 argc); | 704 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 809 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 705 |
| 810 if (code->IsUndefined()) { | 706 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); |
| 811 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); | 707 Handle<Code> code = |
| 812 { MaybeObject* maybe_code = | 708 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object), |
| 813 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name); | 709 holder, name); |
| 814 if (!maybe_code->ToObject(&code)) return maybe_code; | 710 ASSERT_EQ(flags, code->flags()); |
| 815 } | 711 PROFILE(isolate(), |
| 816 ASSERT_EQ(flags, Code::cast(code)->flags()); | 712 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 817 PROFILE(isolate(), | 713 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 818 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 714 JSObject::UpdateMapCodeCache(map_holder, name, code); |
| 819 Code::cast(code), name)); | 715 return code; |
| 820 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); | 716 } |
| 821 Object* result; | 717 |
| 822 { MaybeObject* maybe_result = | 718 |
| 823 map_holder->UpdateMapCodeCache(name, Code::cast(code)); | 719 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 824 if (!maybe_result->ToObject(&result)) return maybe_result; | 720 Handle<JSObject> object, |
| 825 } | 721 Handle<GlobalObject> holder, |
| 826 } | 722 Handle<JSGlobalPropertyCell> cell, |
| 827 return code; | 723 Handle<JSFunction> function, |
| 828 } | 724 Handle<String> name) { |
| 829 | 725 CALL_HEAP_FUNCTION( |
| 830 | 726 isolate(), |
| 831 MaybeObject* StubCache::ComputeCallNormal(int argc, | 727 (set_failure(NULL), |
| 728 CompileCallGlobal(*object, *holder, *cell, *function, *name)), |
| 729 Code); |
| 730 } |
| 731 |
| 732 |
| 733 Handle<Code> StubCache::ComputeCallGlobal(int argc, |
| 832 Code::Kind kind, | 734 Code::Kind kind, |
| 833 Code::ExtraICState extra_ic_state, | 735 Code::ExtraICState extra_state, |
| 834 String* name, | 736 Handle<String> name, |
| 835 JSObject* receiver) { | 737 Handle<JSObject> receiver, |
| 836 Object* code; | 738 Handle<GlobalObject> holder, |
| 837 { MaybeObject* maybe_code = ComputeCallNormal(argc, kind, extra_ic_state); | 739 Handle<JSGlobalPropertyCell> cell, |
| 838 if (!maybe_code->ToObject(&code)) return maybe_code; | 740 Handle<JSFunction> function) { |
| 839 } | |
| 840 return code; | |
| 841 } | |
| 842 | |
| 843 | |
| 844 MaybeObject* StubCache::ComputeCallGlobal(int argc, | |
| 845 Code::Kind kind, | |
| 846 Code::ExtraICState extra_ic_state, | |
| 847 String* name, | |
| 848 JSObject* receiver, | |
| 849 GlobalObject* holder, | |
| 850 JSGlobalPropertyCell* cell, | |
| 851 JSFunction* function) { | |
| 852 InlineCacheHolderFlag cache_holder = | 741 InlineCacheHolderFlag cache_holder = |
| 853 IC::GetCodeCacheForObject(receiver, holder); | 742 IC::GetCodeCacheForObject(*receiver, *holder); |
| 854 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder); | 743 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder)); |
| 855 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 744 Code::Flags flags = |
| 856 NORMAL, | 745 Code::ComputeMonomorphicFlags(kind, NORMAL, extra_state, |
| 857 extra_ic_state, | 746 cache_holder, argc); |
| 858 cache_holder, | 747 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags)); |
| 859 argc); | 748 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 860 Object* code = map_holder->map()->FindInCodeCache(name, flags); | 749 |
| 861 if (code->IsUndefined()) { | 750 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); |
| 862 // If the function hasn't been compiled yet, we cannot do it now | 751 Handle<Code> code = |
| 863 // because it may cause GC. To avoid this issue, we return an | 752 compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
| 864 // internal error which will make sure we do not update any | 753 ASSERT_EQ(flags, code->flags()); |
| 865 // caches. | 754 PROFILE(isolate(), |
| 866 if (!function->is_compiled()) return Failure::InternalError(); | 755 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
| 867 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder); | 756 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
| 868 { MaybeObject* maybe_code = | 757 JSObject::UpdateMapCodeCache(map_holder, name, code); |
| 869 compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 758 return code; |
| 870 if (!maybe_code->ToObject(&code)) return maybe_code; | 759 } |
| 871 } | 760 |
| 872 ASSERT_EQ(flags, Code::cast(code)->flags()); | 761 |
| 873 PROFILE(isolate(), | 762 static void FillCache(Isolate* isolate, Handle<Code> code) { |
| 874 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 763 Handle<NumberDictionary> dictionary = |
| 875 Code::cast(code), name)); | 764 NumberDictionarySet(isolate->factory()->non_monomorphic_cache(), |
| 876 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code))); | 765 code->flags(), |
| 877 Object* result; | 766 code, |
| 878 { MaybeObject* maybe_result = | 767 PropertyDetails(NONE, NORMAL)); |
| 879 map_holder->UpdateMapCodeCache(name, Code::cast(code)); | 768 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
| 880 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 881 } | |
| 882 } | |
| 883 return code; | |
| 884 } | |
| 885 | |
| 886 | |
| 887 static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) { | |
| 888 // Use raw_unchecked... so we don't get assert failures during GC. | |
| 889 NumberDictionary* dictionary = | |
| 890 isolate->heap()->raw_unchecked_non_monomorphic_cache(); | |
| 891 int entry = dictionary->FindEntry(isolate, flags); | |
| 892 if (entry != -1) return dictionary->ValueAt(entry); | |
| 893 return isolate->heap()->raw_unchecked_undefined_value(); | |
| 894 } | |
| 895 | |
| 896 | |
| 897 MUST_USE_RESULT static MaybeObject* ProbeCache(Isolate* isolate, | |
| 898 Code::Flags flags) { | |
| 899 Heap* heap = isolate->heap(); | |
| 900 Object* probe = GetProbeValue(isolate, flags); | |
| 901 if (probe != heap->undefined_value()) return probe; | |
| 902 // Seed the cache with an undefined value to make sure that any | |
| 903 // generated code object can always be inserted into the cache | |
| 904 // without causing allocation failures. | |
| 905 Object* result; | |
| 906 { MaybeObject* maybe_result = | |
| 907 heap->non_monomorphic_cache()->AtNumberPut(flags, | |
| 908 heap->undefined_value()); | |
| 909 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 910 } | |
| 911 heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result)); | |
| 912 return probe; | |
| 913 } | |
| 914 | |
| 915 | |
| 916 static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) { | |
| 917 Object* code; | |
| 918 if (maybe_code->ToObject(&code)) { | |
| 919 if (code->IsCode()) { | |
| 920 Heap* heap = isolate->heap(); | |
| 921 int entry = heap->non_monomorphic_cache()->FindEntry( | |
| 922 Code::cast(code)->flags()); | |
| 923 // The entry must be present see comment in ProbeCache. | |
| 924 ASSERT(entry != -1); | |
| 925 ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) == | |
| 926 heap->undefined_value()); | |
| 927 heap->non_monomorphic_cache()->ValueAtPut(entry, code); | |
| 928 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code); | |
| 929 } | |
| 930 } | |
| 931 return maybe_code; | |
| 932 } | 769 } |
| 933 | 770 |
| 934 | 771 |
| 935 Code* StubCache::FindCallInitialize(int argc, | 772 Code* StubCache::FindCallInitialize(int argc, |
| 936 RelocInfo::Mode mode, | 773 RelocInfo::Mode mode, |
| 937 Code::Kind kind) { | 774 Code::Kind kind) { |
| 938 Code::ExtraICState extra_state = | 775 Code::ExtraICState extra_state = |
| 939 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | | 776 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | |
| 940 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); | 777 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 941 Code::Flags flags = Code::ComputeFlags(kind, | 778 Code::Flags flags = |
| 942 UNINITIALIZED, | 779 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc); |
| 943 extra_state, | 780 |
| 944 NORMAL, | 781 // Use raw_unchecked... so we don't get assert failures during GC. |
| 945 argc); | 782 NumberDictionary* dictionary = |
| 946 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked(); | 783 isolate()->heap()->raw_unchecked_non_monomorphic_cache(); |
| 947 ASSERT(result != heap()->undefined_value()); | 784 int entry = dictionary->FindEntry(isolate(), flags); |
| 785 ASSERT(entry != -1); |
| 786 Object* code = dictionary->ValueAt(entry); |
| 948 // This might be called during the marking phase of the collector | 787 // This might be called during the marking phase of the collector |
| 949 // hence the unchecked cast. | 788 // hence the unchecked cast. |
| 950 return reinterpret_cast<Code*>(result); | 789 return reinterpret_cast<Code*>(code); |
| 951 } | 790 } |
| 952 | 791 |
| 953 | 792 |
| 954 MaybeObject* StubCache::ComputeCallInitialize(int argc, | 793 Handle<Code> StubCache::ComputeCallInitialize(int argc, |
| 955 RelocInfo::Mode mode, | 794 RelocInfo::Mode mode, |
| 956 Code::Kind kind) { | 795 Code::Kind kind) { |
| 957 Code::ExtraICState extra_state = | 796 Code::ExtraICState extra_state = |
| 958 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | | 797 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) | |
| 959 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); | 798 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 960 Code::Flags flags = Code::ComputeFlags(kind, | 799 Code::Flags flags = |
| 961 UNINITIALIZED, | 800 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc); |
| 962 extra_state, | 801 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 963 NORMAL, | 802 int entry = cache->FindEntry(isolate_, flags); |
| 964 argc); | 803 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 965 Object* probe; | 804 |
| 966 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 805 StubCompiler compiler(isolate_); |
| 967 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 806 Handle<Code> code = compiler.CompileCallInitialize(flags); |
| 968 } | 807 FillCache(isolate_, code); |
| 969 if (!probe->IsUndefined()) return probe; | 808 return code; |
| 970 StubCompiler compiler; | 809 } |
| 971 return FillCache(isolate_, compiler.CompileCallInitialize(flags)); | 810 |
| 972 } | 811 |
| 973 | 812 Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) { |
| 974 | 813 return ComputeCallInitialize(argc, mode, Code::CALL_IC); |
| 975 Handle<Code> StubCache::ComputeCallInitialize(int argc, | |
| 976 RelocInfo::Mode mode) { | |
| 977 CALL_HEAP_FUNCTION(isolate_, | |
| 978 ComputeCallInitialize(argc, mode, Code::CALL_IC), | |
| 979 Code); | |
| 980 } | 814 } |
| 981 | 815 |
| 982 | 816 |
| 983 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) { | 817 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) { |
| 984 CALL_HEAP_FUNCTION( | 818 return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET, |
| 985 isolate_, | 819 Code::KEYED_CALL_IC); |
| 986 ComputeCallInitialize(argc, RelocInfo::CODE_TARGET, Code::KEYED_CALL_IC), | 820 } |
| 987 Code); | 821 |
| 988 } | 822 |
| 989 | 823 Handle<Code> StubCache::ComputeCallPreMonomorphic( |
| 990 | |
| 991 MaybeObject* StubCache::ComputeCallPreMonomorphic( | |
| 992 int argc, | 824 int argc, |
| 993 Code::Kind kind, | 825 Code::Kind kind, |
| 994 Code::ExtraICState extra_ic_state) { | 826 Code::ExtraICState extra_state) { |
| 995 Code::Flags flags = Code::ComputeFlags(kind, | 827 Code::Flags flags = |
| 996 PREMONOMORPHIC, | 828 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, NORMAL, argc); |
| 997 extra_ic_state, | 829 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 998 NORMAL, | 830 int entry = cache->FindEntry(isolate_, flags); |
| 999 argc); | 831 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 1000 Object* probe; | 832 |
| 1001 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 833 StubCompiler compiler(isolate_); |
| 1002 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 834 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags); |
| 1003 } | 835 FillCache(isolate_, code); |
| 1004 if (!probe->IsUndefined()) return probe; | 836 return code; |
| 1005 StubCompiler compiler; | 837 } |
| 1006 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags)); | 838 |
| 1007 } | 839 |
| 1008 | 840 Handle<Code> StubCache::ComputeCallNormal(int argc, |
| 1009 | |
| 1010 MaybeObject* StubCache::ComputeCallNormal(int argc, | |
| 1011 Code::Kind kind, | 841 Code::Kind kind, |
| 1012 Code::ExtraICState extra_ic_state) { | 842 Code::ExtraICState extra_state) { |
| 1013 Code::Flags flags = Code::ComputeFlags(kind, | 843 Code::Flags flags = |
| 1014 MONOMORPHIC, | 844 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, NORMAL, argc); |
| 1015 extra_ic_state, | 845 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 1016 NORMAL, | 846 int entry = cache->FindEntry(isolate_, flags); |
| 1017 argc); | 847 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 1018 Object* probe; | 848 |
| 1019 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 849 StubCompiler compiler(isolate_); |
| 1020 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 850 Handle<Code> code = compiler.CompileCallNormal(flags); |
| 1021 } | 851 FillCache(isolate_, code); |
| 1022 if (!probe->IsUndefined()) return probe; | 852 return code; |
| 1023 StubCompiler compiler; | 853 } |
| 1024 return FillCache(isolate_, compiler.CompileCallNormal(flags)); | 854 |
| 1025 } | 855 |
| 1026 | 856 Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) { |
| 1027 | |
| 1028 MaybeObject* StubCache::ComputeCallArguments(int argc, Code::Kind kind) { | |
| 1029 ASSERT(kind == Code::KEYED_CALL_IC); | 857 ASSERT(kind == Code::KEYED_CALL_IC); |
| 1030 Code::Flags flags = Code::ComputeFlags(kind, | 858 Code::Flags flags = |
| 1031 MEGAMORPHIC, | 859 Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState, |
| 1032 Code::kNoExtraICState, | 860 NORMAL, argc); |
| 1033 NORMAL, | 861 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 1034 argc); | 862 int entry = cache->FindEntry(isolate_, flags); |
| 1035 Object* probe; | 863 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 1036 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 864 |
| 1037 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 865 StubCompiler compiler(isolate_); |
| 1038 } | 866 Handle<Code> code = compiler.CompileCallArguments(flags); |
| 1039 if (!probe->IsUndefined()) return probe; | 867 FillCache(isolate_, code); |
| 1040 StubCompiler compiler; | 868 return code; |
| 1041 return FillCache(isolate_, compiler.CompileCallArguments(flags)); | 869 } |
| 1042 } | 870 |
| 1043 | 871 |
| 1044 | 872 Handle<Code> StubCache::ComputeCallMegamorphic( |
| 1045 MaybeObject* StubCache::ComputeCallMegamorphic( | |
| 1046 int argc, | 873 int argc, |
| 1047 Code::Kind kind, | 874 Code::Kind kind, |
| 1048 Code::ExtraICState extra_ic_state) { | 875 Code::ExtraICState extra_state) { |
| 1049 Code::Flags flags = Code::ComputeFlags(kind, | 876 Code::Flags flags = |
| 1050 MEGAMORPHIC, | 877 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state, |
| 1051 extra_ic_state, | 878 NORMAL, argc); |
| 1052 NORMAL, | 879 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 1053 argc); | 880 int entry = cache->FindEntry(isolate_, flags); |
| 1054 Object* probe; | 881 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 1055 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 882 |
| 1056 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 883 StubCompiler compiler(isolate_); |
| 1057 } | 884 Handle<Code> code = compiler.CompileCallMegamorphic(flags); |
| 1058 if (!probe->IsUndefined()) return probe; | 885 FillCache(isolate_, code); |
| 1059 StubCompiler compiler; | 886 return code; |
| 1060 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags)); | 887 } |
| 1061 } | 888 |
| 1062 | 889 |
| 1063 | 890 Handle<Code> StubCache::ComputeCallMiss(int argc, |
| 1064 MaybeObject* StubCache::ComputeCallMiss(int argc, | |
| 1065 Code::Kind kind, | 891 Code::Kind kind, |
| 1066 Code::ExtraICState extra_ic_state) { | 892 Code::ExtraICState extra_state) { |
| 1067 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs | 893 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs |
| 1068 // and monomorphic stubs are not mixed up together in the stub cache. | 894 // and monomorphic stubs are not mixed up together in the stub cache. |
| 1069 Code::Flags flags = Code::ComputeFlags(kind, | 895 Code::Flags flags = |
| 1070 MONOMORPHIC_PROTOTYPE_FAILURE, | 896 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state, |
| 1071 extra_ic_state, | 897 NORMAL, argc, OWN_MAP); |
| 1072 NORMAL, | 898 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 1073 argc, | 899 int entry = cache->FindEntry(isolate_, flags); |
| 1074 OWN_MAP); | 900 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 1075 Object* probe; | 901 |
| 1076 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 902 StubCompiler compiler(isolate_); |
| 1077 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 903 Handle<Code> code = compiler.CompileCallMiss(flags); |
| 1078 } | 904 FillCache(isolate_, code); |
| 1079 if (!probe->IsUndefined()) return probe; | 905 return code; |
| 1080 StubCompiler compiler; | 906 } |
| 1081 return FillCache(isolate_, compiler.CompileCallMiss(flags)); | 907 |
| 908 |
| 909 // The CallStubCompiler needs a version of ComputeCallMiss that does not |
| 910 // perform GC. This function is temporary, because the stub cache but not |
| 911 // yet the stub compiler uses handles. |
| 912 MaybeObject* StubCache::TryComputeCallMiss(int argc, |
| 913 Code::Kind kind, |
| 914 Code::ExtraICState extra_state) { |
| 915 Code::Flags flags = |
| 916 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state, |
| 917 NORMAL, argc, OWN_MAP); |
| 918 NumberDictionary* cache = isolate_->heap()->non_monomorphic_cache(); |
| 919 int entry = cache->FindEntry(isolate_, flags); |
| 920 if (entry != -1) return cache->ValueAt(entry); |
| 921 |
| 922 StubCompiler compiler(isolate_); |
| 923 Code* code = NULL; |
| 924 MaybeObject* maybe_code = compiler.TryCompileCallMiss(flags); |
| 925 if (!maybe_code->To(&code)) return maybe_code; |
| 926 |
| 927 NumberDictionary* new_cache = NULL; |
| 928 MaybeObject* maybe_new_cache = cache->AtNumberPut(flags, code); |
| 929 if (!maybe_new_cache->To(&new_cache)) return maybe_new_cache; |
| 930 isolate_->heap()->public_set_non_monomorphic_cache(new_cache); |
| 931 |
| 932 return code; |
| 1082 } | 933 } |
| 1083 | 934 |
| 1084 | 935 |
| 1085 #ifdef ENABLE_DEBUGGER_SUPPORT | 936 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1086 MaybeObject* StubCache::ComputeCallDebugBreak( | 937 Handle<Code> StubCache::ComputeCallDebugBreak(int argc, |
| 1087 int argc, | 938 Code::Kind kind) { |
| 1088 Code::Kind kind) { | |
| 1089 // Extra IC state is irrelevant for debug break ICs. They jump to | 939 // Extra IC state is irrelevant for debug break ICs. They jump to |
| 1090 // the actual call ic to carry out the work. | 940 // the actual call ic to carry out the work. |
| 1091 Code::Flags flags = Code::ComputeFlags(kind, | 941 Code::Flags flags = |
| 1092 DEBUG_BREAK, | 942 Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState, |
| 1093 Code::kNoExtraICState, | 943 NORMAL, argc); |
| 1094 NORMAL, | 944 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 1095 argc); | 945 int entry = cache->FindEntry(isolate_, flags); |
| 1096 Object* probe; | 946 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 1097 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 947 |
| 1098 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 948 StubCompiler compiler(isolate_); |
| 1099 } | 949 Handle<Code> code = compiler.CompileCallDebugBreak(flags); |
| 1100 if (!probe->IsUndefined()) return probe; | 950 FillCache(isolate_, code); |
| 1101 StubCompiler compiler; | 951 return code; |
| 1102 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags)); | 952 } |
| 1103 } | 953 |
| 1104 | 954 |
| 1105 | 955 Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc, |
| 1106 MaybeObject* StubCache::ComputeCallDebugPrepareStepIn( | 956 Code::Kind kind) { |
| 1107 int argc, | |
| 1108 Code::Kind kind) { | |
| 1109 // Extra IC state is irrelevant for debug break ICs. They jump to | 957 // Extra IC state is irrelevant for debug break ICs. They jump to |
| 1110 // the actual call ic to carry out the work. | 958 // the actual call ic to carry out the work. |
| 1111 Code::Flags flags = Code::ComputeFlags(kind, | 959 Code::Flags flags = |
| 1112 DEBUG_PREPARE_STEP_IN, | 960 Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState, |
| 1113 Code::kNoExtraICState, | 961 NORMAL, argc); |
| 1114 NORMAL, | 962 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
| 1115 argc); | 963 int entry = cache->FindEntry(isolate_, flags); |
| 1116 Object* probe; | 964 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 1117 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags); | 965 |
| 1118 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 966 StubCompiler compiler(isolate_); |
| 1119 } | 967 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags); |
| 1120 if (!probe->IsUndefined()) return probe; | 968 FillCache(isolate_, code); |
| 1121 StubCompiler compiler; | 969 return code; |
| 1122 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags)); | |
| 1123 } | 970 } |
| 1124 #endif | 971 #endif |
| 1125 | 972 |
| 1126 | 973 |
| 1127 void StubCache::Clear() { | 974 void StubCache::Clear() { |
| 1128 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 975 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
| 1129 for (int i = 0; i < kPrimaryTableSize; i++) { | 976 for (int i = 0; i < kPrimaryTableSize; i++) { |
| 1130 primary_[i].key = heap()->empty_string(); | 977 primary_[i].key = heap()->empty_string(); |
| 1131 primary_[i].value = empty; | 978 primary_[i].value = empty; |
| 1132 } | 979 } |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1377 | 1224 |
| 1378 | 1225 |
| 1379 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { | 1226 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { |
| 1380 JSObject* receiver = JSObject::cast(args[0]); | 1227 JSObject* receiver = JSObject::cast(args[0]); |
| 1381 ASSERT(args.smi_at(1) >= 0); | 1228 ASSERT(args.smi_at(1) >= 0); |
| 1382 uint32_t index = args.smi_at(1); | 1229 uint32_t index = args.smi_at(1); |
| 1383 return receiver->GetElementWithInterceptor(receiver, index); | 1230 return receiver->GetElementWithInterceptor(receiver, index); |
| 1384 } | 1231 } |
| 1385 | 1232 |
| 1386 | 1233 |
| 1387 MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) { | 1234 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) { |
| 1388 HandleScope scope(isolate()); | |
| 1389 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1235 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1390 Code::Kind kind = Code::ExtractKindFromFlags(flags); | 1236 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1391 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags); | 1237 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
| 1392 if (kind == Code::CALL_IC) { | 1238 if (kind == Code::CALL_IC) { |
| 1393 CallIC::GenerateInitialize(masm(), argc, extra_ic_state); | 1239 CallIC::GenerateInitialize(masm(), argc, extra_state); |
| 1394 } else { | 1240 } else { |
| 1395 KeyedCallIC::GenerateInitialize(masm(), argc); | 1241 KeyedCallIC::GenerateInitialize(masm(), argc); |
| 1396 } | 1242 } |
| 1397 Object* result; | 1243 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize"); |
| 1398 { MaybeObject* maybe_result = | |
| 1399 GetCodeWithFlags(flags, "CompileCallInitialize"); | |
| 1400 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1401 } | |
| 1402 isolate()->counters()->call_initialize_stubs()->Increment(); | 1244 isolate()->counters()->call_initialize_stubs()->Increment(); |
| 1403 Code* code = Code::cast(result); | |
| 1404 USE(code); | |
| 1405 PROFILE(isolate(), | 1245 PROFILE(isolate(), |
| 1406 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), | 1246 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), |
| 1407 code, code->arguments_count())); | 1247 *code, code->arguments_count())); |
| 1408 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code))); | 1248 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code)); |
| 1409 return result; | 1249 return code; |
| 1410 } | 1250 } |
| 1411 | 1251 |
| 1412 | 1252 |
| 1413 MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { | 1253 Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { |
| 1414 HandleScope scope(isolate()); | |
| 1415 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1254 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1416 // The code of the PreMonomorphic stub is the same as the code | 1255 // The code of the PreMonomorphic stub is the same as the code |
| 1417 // of the Initialized stub. They just differ on the code object flags. | 1256 // of the Initialized stub. They just differ on the code object flags. |
| 1418 Code::Kind kind = Code::ExtractKindFromFlags(flags); | 1257 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1419 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags); | 1258 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
| 1420 if (kind == Code::CALL_IC) { | 1259 if (kind == Code::CALL_IC) { |
| 1421 CallIC::GenerateInitialize(masm(), argc, extra_ic_state); | 1260 CallIC::GenerateInitialize(masm(), argc, extra_state); |
| 1422 } else { | 1261 } else { |
| 1423 KeyedCallIC::GenerateInitialize(masm(), argc); | 1262 KeyedCallIC::GenerateInitialize(masm(), argc); |
| 1424 } | 1263 } |
| 1425 Object* result; | 1264 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); |
| 1426 { MaybeObject* maybe_result = | |
| 1427 GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); | |
| 1428 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1429 } | |
| 1430 isolate()->counters()->call_premonomorphic_stubs()->Increment(); | 1265 isolate()->counters()->call_premonomorphic_stubs()->Increment(); |
| 1431 Code* code = Code::cast(result); | |
| 1432 USE(code); | |
| 1433 PROFILE(isolate(), | 1266 PROFILE(isolate(), |
| 1434 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), | 1267 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), |
| 1435 code, code->arguments_count())); | 1268 *code, code->arguments_count())); |
| 1436 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code))); | 1269 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code)); |
| 1437 return result; | 1270 return code; |
| 1438 } | 1271 } |
| 1439 | 1272 |
| 1440 | 1273 |
| 1441 MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) { | 1274 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) { |
| 1442 HandleScope scope(isolate()); | |
| 1443 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1275 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1444 Code::Kind kind = Code::ExtractKindFromFlags(flags); | 1276 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1445 if (kind == Code::CALL_IC) { | 1277 if (kind == Code::CALL_IC) { |
| 1446 // Call normal is always with a explict receiver. | 1278 // Call normal is always with a explict receiver. |
| 1447 ASSERT(!CallIC::Contextual::decode( | 1279 ASSERT(!CallIC::Contextual::decode( |
| 1448 Code::ExtractExtraICStateFromFlags(flags))); | 1280 Code::ExtractExtraICStateFromFlags(flags))); |
| 1449 CallIC::GenerateNormal(masm(), argc); | 1281 CallIC::GenerateNormal(masm(), argc); |
| 1450 } else { | 1282 } else { |
| 1451 KeyedCallIC::GenerateNormal(masm(), argc); | 1283 KeyedCallIC::GenerateNormal(masm(), argc); |
| 1452 } | 1284 } |
| 1453 Object* result; | 1285 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal"); |
| 1454 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal"); | |
| 1455 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1456 } | |
| 1457 isolate()->counters()->call_normal_stubs()->Increment(); | 1286 isolate()->counters()->call_normal_stubs()->Increment(); |
| 1458 Code* code = Code::cast(result); | |
| 1459 USE(code); | |
| 1460 PROFILE(isolate(), | 1287 PROFILE(isolate(), |
| 1461 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), | 1288 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), |
| 1462 code, code->arguments_count())); | 1289 *code, code->arguments_count())); |
| 1463 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code))); | 1290 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code)); |
| 1464 return result; | 1291 return code; |
| 1465 } | 1292 } |
| 1466 | 1293 |
| 1467 | 1294 |
| 1468 MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { | 1295 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) { |
| 1296 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1297 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1298 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
| 1299 if (kind == Code::CALL_IC) { |
| 1300 CallIC::GenerateMegamorphic(masm(), argc, extra_state); |
| 1301 } else { |
| 1302 KeyedCallIC::GenerateMegamorphic(masm(), argc); |
| 1303 } |
| 1304 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic"); |
| 1305 isolate()->counters()->call_megamorphic_stubs()->Increment(); |
| 1306 PROFILE(isolate(), |
| 1307 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), |
| 1308 *code, code->arguments_count())); |
| 1309 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code)); |
| 1310 return code; |
| 1311 } |
| 1312 |
| 1313 |
| 1314 Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) { |
| 1315 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1316 KeyedCallIC::GenerateNonStrictArguments(masm(), argc); |
| 1317 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments"); |
| 1318 PROFILE(isolate(), |
| 1319 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), |
| 1320 CALL_MEGAMORPHIC_TAG), |
| 1321 *code, code->arguments_count())); |
| 1322 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code)); |
| 1323 return code; |
| 1324 } |
| 1325 |
| 1326 |
| 1327 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) { |
| 1328 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1329 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1330 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
| 1331 if (kind == Code::CALL_IC) { |
| 1332 CallIC::GenerateMiss(masm(), argc, extra_state); |
| 1333 } else { |
| 1334 KeyedCallIC::GenerateMiss(masm(), argc); |
| 1335 } |
| 1336 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss"); |
| 1337 isolate()->counters()->call_megamorphic_stubs()->Increment(); |
| 1338 PROFILE(isolate(), |
| 1339 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), |
| 1340 *code, code->arguments_count())); |
| 1341 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code)); |
| 1342 return code; |
| 1343 } |
| 1344 |
| 1345 |
| 1346 // TODO(kmillikin): This annoying raw pointer implementation should be |
| 1347 // eliminated when the stub compiler no longer needs it. |
| 1348 MaybeObject* StubCompiler::TryCompileCallMiss(Code::Flags flags) { |
| 1469 HandleScope scope(isolate()); | 1349 HandleScope scope(isolate()); |
| 1470 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1350 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1471 Code::Kind kind = Code::ExtractKindFromFlags(flags); | 1351 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1472 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags); | 1352 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
| 1473 if (kind == Code::CALL_IC) { | 1353 if (kind == Code::CALL_IC) { |
| 1474 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state); | 1354 CallIC::GenerateMiss(masm(), argc, extra_state); |
| 1475 } else { | |
| 1476 KeyedCallIC::GenerateMegamorphic(masm(), argc); | |
| 1477 } | |
| 1478 Object* result; | |
| 1479 { MaybeObject* maybe_result = | |
| 1480 GetCodeWithFlags(flags, "CompileCallMegamorphic"); | |
| 1481 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1482 } | |
| 1483 isolate()->counters()->call_megamorphic_stubs()->Increment(); | |
| 1484 Code* code = Code::cast(result); | |
| 1485 USE(code); | |
| 1486 PROFILE(isolate(), | |
| 1487 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), | |
| 1488 code, code->arguments_count())); | |
| 1489 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code))); | |
| 1490 return result; | |
| 1491 } | |
| 1492 | |
| 1493 | |
| 1494 MaybeObject* StubCompiler::CompileCallArguments(Code::Flags flags) { | |
| 1495 HandleScope scope(isolate()); | |
| 1496 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1497 KeyedCallIC::GenerateNonStrictArguments(masm(), argc); | |
| 1498 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1499 Object* result; | |
| 1500 { MaybeObject* maybe_result = | |
| 1501 GetCodeWithFlags(flags, "CompileCallArguments"); | |
| 1502 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1503 } | |
| 1504 Code* code = Code::cast(result); | |
| 1505 USE(code); | |
| 1506 PROFILE(isolate(), | |
| 1507 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), | |
| 1508 code, code->arguments_count())); | |
| 1509 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code))); | |
| 1510 return result; | |
| 1511 } | |
| 1512 | |
| 1513 | |
| 1514 MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) { | |
| 1515 HandleScope scope(isolate()); | |
| 1516 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
| 1517 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1518 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags); | |
| 1519 if (kind == Code::CALL_IC) { | |
| 1520 CallIC::GenerateMiss(masm(), argc, extra_ic_state); | |
| 1521 } else { | 1355 } else { |
| 1522 KeyedCallIC::GenerateMiss(masm(), argc); | 1356 KeyedCallIC::GenerateMiss(masm(), argc); |
| 1523 } | 1357 } |
| 1524 Object* result; | 1358 Object* result; |
| 1525 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss"); | 1359 { MaybeObject* maybe_result = TryGetCodeWithFlags(flags, "CompileCallMiss"); |
| 1526 if (!maybe_result->ToObject(&result)) return maybe_result; | 1360 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1527 } | 1361 } |
| 1528 isolate()->counters()->call_megamorphic_stubs()->Increment(); | 1362 isolate()->counters()->call_megamorphic_stubs()->Increment(); |
| 1529 Code* code = Code::cast(result); | 1363 Code* code = Code::cast(result); |
| 1530 USE(code); | 1364 USE(code); |
| 1531 PROFILE(isolate(), | 1365 PROFILE(isolate(), |
| 1532 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), | 1366 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), |
| 1533 code, code->arguments_count())); | 1367 code, code->arguments_count())); |
| 1534 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code))); | 1368 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code))); |
| 1535 return result; | 1369 return result; |
| 1536 } | 1370 } |
| 1537 | 1371 |
| 1538 | 1372 |
| 1539 #ifdef ENABLE_DEBUGGER_SUPPORT | 1373 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1540 MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | 1374 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) { |
| 1541 HandleScope scope(isolate()); | |
| 1542 Debug::GenerateCallICDebugBreak(masm()); | 1375 Debug::GenerateCallICDebugBreak(masm()); |
| 1543 Object* result; | 1376 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak"); |
| 1544 { MaybeObject* maybe_result = | |
| 1545 GetCodeWithFlags(flags, "CompileCallDebugBreak"); | |
| 1546 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1547 } | |
| 1548 Code* code = Code::cast(result); | |
| 1549 USE(code); | |
| 1550 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
| 1551 USE(kind); | |
| 1552 PROFILE(isolate(), | 1377 PROFILE(isolate(), |
| 1553 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG), | 1378 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), |
| 1554 code, code->arguments_count())); | 1379 CALL_DEBUG_BREAK_TAG), |
| 1555 return result; | 1380 *code, code->arguments_count())); |
| 1381 return code; |
| 1556 } | 1382 } |
| 1557 | 1383 |
| 1558 | 1384 |
| 1559 MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { | 1385 Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { |
| 1560 HandleScope scope(isolate()); | 1386 // Use the same code for the the step in preparations as we do for the |
| 1561 // Use the same code for the the step in preparations as we do for | 1387 // miss case. |
| 1562 // the miss case. | |
| 1563 int argc = Code::ExtractArgumentsCountFromFlags(flags); | 1388 int argc = Code::ExtractArgumentsCountFromFlags(flags); |
| 1564 Code::Kind kind = Code::ExtractKindFromFlags(flags); | 1389 Code::Kind kind = Code::ExtractKindFromFlags(flags); |
| 1565 if (kind == Code::CALL_IC) { | 1390 if (kind == Code::CALL_IC) { |
| 1566 // For the debugger extra ic state is irrelevant. | 1391 // For the debugger extra ic state is irrelevant. |
| 1567 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState); | 1392 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState); |
| 1568 } else { | 1393 } else { |
| 1569 KeyedCallIC::GenerateMiss(masm(), argc); | 1394 KeyedCallIC::GenerateMiss(masm(), argc); |
| 1570 } | 1395 } |
| 1571 Object* result; | 1396 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); |
| 1572 { MaybeObject* maybe_result = | |
| 1573 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); | |
| 1574 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 1575 } | |
| 1576 Code* code = Code::cast(result); | |
| 1577 USE(code); | |
| 1578 PROFILE(isolate(), | 1397 PROFILE(isolate(), |
| 1579 CodeCreateEvent( | 1398 CodeCreateEvent( |
| 1580 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), | 1399 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), |
| 1581 code, | 1400 *code, |
| 1582 code->arguments_count())); | 1401 code->arguments_count())); |
| 1583 return result; | 1402 return code; |
| 1584 } | 1403 } |
| 1585 #endif | 1404 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1586 | 1405 |
| 1587 #undef CALL_LOGGER_TAG | 1406 #undef CALL_LOGGER_TAG |
| 1588 | 1407 |
| 1589 MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, | 1408 |
| 1409 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
| 1590 const char* name) { | 1410 const char* name) { |
| 1411 // Create code object in the heap. |
| 1412 CodeDesc desc; |
| 1413 masm_.GetCode(&desc); |
| 1414 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); |
| 1415 #ifdef ENABLE_DISASSEMBLER |
| 1416 if (FLAG_print_code_stubs) code->Disassemble(name); |
| 1417 #endif |
| 1418 return code; |
| 1419 } |
| 1420 |
| 1421 |
| 1422 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
| 1423 Handle<String> name) { |
| 1424 return (FLAG_print_code_stubs && !name.is_null()) |
| 1425 ? GetCodeWithFlags(flags, *name->ToCString()) |
| 1426 : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL)); |
| 1427 } |
| 1428 |
| 1429 |
| 1430 MaybeObject* StubCompiler::TryGetCodeWithFlags(Code::Flags flags, |
| 1431 const char* name) { |
| 1591 // Check for allocation failures during stub compilation. | 1432 // Check for allocation failures during stub compilation. |
| 1592 if (failure_->IsFailure()) return failure_; | 1433 if (failure_->IsFailure()) return failure_; |
| 1593 | 1434 |
| 1594 // Create code object in the heap. | 1435 // Create code object in the heap. |
| 1595 CodeDesc desc; | 1436 CodeDesc desc; |
| 1596 masm_.GetCode(&desc); | 1437 masm_.GetCode(&desc); |
| 1597 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject()); | 1438 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject()); |
| 1598 #ifdef ENABLE_DISASSEMBLER | 1439 #ifdef ENABLE_DISASSEMBLER |
| 1599 if (FLAG_print_code_stubs && !result->IsFailure()) { | 1440 if (FLAG_print_code_stubs && !result->IsFailure()) { |
| 1600 Code::cast(result->ToObjectUnchecked())->Disassemble(name); | 1441 Code::cast(result->ToObjectUnchecked())->Disassemble(name); |
| 1601 } | 1442 } |
| 1602 #endif | 1443 #endif |
| 1603 return result; | 1444 return result; |
| 1604 } | 1445 } |
| 1605 | 1446 |
| 1606 | 1447 |
| 1607 MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) { | 1448 MaybeObject* StubCompiler::TryGetCodeWithFlags(Code::Flags flags, |
| 1608 if (FLAG_print_code_stubs && (name != NULL)) { | 1449 String* name) { |
| 1609 return GetCodeWithFlags(flags, *name->ToCString()); | 1450 if (FLAG_print_code_stubs && name != NULL) { |
| 1451 return TryGetCodeWithFlags(flags, *name->ToCString()); |
| 1610 } | 1452 } |
| 1611 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL)); | 1453 return TryGetCodeWithFlags(flags, reinterpret_cast<char*>(NULL)); |
| 1612 } | 1454 } |
| 1613 | 1455 |
| 1614 | 1456 |
| 1615 void StubCompiler::LookupPostInterceptor(JSObject* holder, | 1457 void StubCompiler::LookupPostInterceptor(JSObject* holder, |
| 1616 String* name, | 1458 String* name, |
| 1617 LookupResult* lookup) { | 1459 LookupResult* lookup) { |
| 1618 holder->LocalLookupRealNamedProperty(name, lookup); | 1460 holder->LocalLookupRealNamedProperty(name, lookup); |
| 1619 if (!lookup->IsProperty()) { | 1461 if (!lookup->IsProperty()) { |
| 1620 lookup->NotFound(); | 1462 lookup->NotFound(); |
| 1621 Object* proto = holder->GetPrototype(); | 1463 Object* proto = holder->GetPrototype(); |
| 1622 if (!proto->IsNull()) { | 1464 if (!proto->IsNull()) { |
| 1623 proto->Lookup(name, lookup); | 1465 proto->Lookup(name, lookup); |
| 1624 } | 1466 } |
| 1625 } | 1467 } |
| 1626 } | 1468 } |
| 1627 | 1469 |
| 1628 | 1470 |
| 1471 Handle<Code> LoadStubCompiler::GetCode(PropertyType type, Handle<String> name) { |
| 1472 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type); |
| 1473 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1474 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
| 1475 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
| 1476 return code; |
| 1477 } |
| 1629 | 1478 |
| 1630 MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) { | 1479 |
| 1480 // TODO(ulan): Eliminate this function when the stub cache is fully |
| 1481 // handlified. |
| 1482 MaybeObject* LoadStubCompiler::TryGetCode(PropertyType type, String* name) { |
| 1631 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type); | 1483 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type); |
| 1632 MaybeObject* result = GetCodeWithFlags(flags, name); | 1484 MaybeObject* result = TryGetCodeWithFlags(flags, name); |
| 1633 if (!result->IsFailure()) { | 1485 if (!result->IsFailure()) { |
| 1634 PROFILE(isolate(), | 1486 PROFILE(isolate(), |
| 1635 CodeCreateEvent(Logger::LOAD_IC_TAG, | 1487 CodeCreateEvent(Logger::LOAD_IC_TAG, |
| 1636 Code::cast(result->ToObjectUnchecked()), | 1488 Code::cast(result->ToObjectUnchecked()), |
| 1637 name)); | 1489 name)); |
| 1638 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, | 1490 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, |
| 1639 name, | 1491 name, |
| 1640 Code::cast(result->ToObjectUnchecked()))); | 1492 Code::cast(result->ToObjectUnchecked()))); |
| 1641 } | 1493 } |
| 1642 return result; | 1494 return result; |
| 1643 } | 1495 } |
| 1644 | 1496 |
| 1645 | 1497 |
| 1646 MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type, | 1498 Handle<Code> KeyedLoadStubCompiler::GetCode(PropertyType type, |
| 1499 Handle<String> name, |
| 1500 InlineCacheState state) { |
| 1501 Code::Flags flags = Code::ComputeFlags( |
| 1502 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); |
| 1503 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1504 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
| 1505 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
| 1506 return code; |
| 1507 } |
| 1508 |
| 1509 // TODO(ulan): Eliminate this function when the stub cache is fully |
| 1510 // handlified. |
| 1511 MaybeObject* KeyedLoadStubCompiler::TryGetCode(PropertyType type, |
| 1647 String* name, | 1512 String* name, |
| 1648 InlineCacheState state) { | 1513 InlineCacheState state) { |
| 1649 Code::Flags flags = Code::ComputeFlags( | 1514 Code::Flags flags = Code::ComputeFlags( |
| 1650 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); | 1515 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); |
| 1651 MaybeObject* result = GetCodeWithFlags(flags, name); | 1516 MaybeObject* result = TryGetCodeWithFlags(flags, name); |
| 1652 if (!result->IsFailure()) { | 1517 if (!result->IsFailure()) { |
| 1653 PROFILE(isolate(), | 1518 PROFILE(isolate(), |
| 1654 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, | 1519 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, |
| 1655 Code::cast(result->ToObjectUnchecked()), | 1520 Code::cast(result->ToObjectUnchecked()), |
| 1656 name)); | 1521 name)); |
| 1657 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, | 1522 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, |
| 1658 name, | 1523 name, |
| 1659 Code::cast(result->ToObjectUnchecked()))); | 1524 Code::cast(result->ToObjectUnchecked()))); |
| 1660 } | 1525 } |
| 1661 return result; | 1526 return result; |
| 1662 } | 1527 } |
| 1663 | 1528 |
| 1664 | 1529 |
| 1665 MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) { | 1530 Handle<Code> StoreStubCompiler::GetCode(PropertyType type, |
| 1531 Handle<String> name) { |
| 1666 Code::Flags flags = | 1532 Code::Flags flags = |
| 1667 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_); | 1533 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_); |
| 1668 MaybeObject* result = GetCodeWithFlags(flags, name); | 1534 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1669 if (!result->IsFailure()) { | 1535 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
| 1670 PROFILE(isolate(), | 1536 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
| 1671 CodeCreateEvent(Logger::STORE_IC_TAG, | 1537 return code; |
| 1672 Code::cast(result->ToObjectUnchecked()), | |
| 1673 name)); | |
| 1674 GDBJIT(AddCode(GDBJITInterface::STORE_IC, | |
| 1675 name, | |
| 1676 Code::cast(result->ToObjectUnchecked()))); | |
| 1677 } | |
| 1678 return result; | |
| 1679 } | 1538 } |
| 1680 | 1539 |
| 1681 | 1540 |
| 1682 MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, | 1541 Handle<Code> KeyedStoreStubCompiler::GetCode(PropertyType type, |
| 1683 String* name, | 1542 Handle<String> name, |
| 1684 InlineCacheState state) { | 1543 InlineCacheState state) { |
| 1685 Code::Flags flags = | 1544 Code::Flags flags = |
| 1686 Code::ComputeFlags(Code::KEYED_STORE_IC, state, strict_mode_, type); | 1545 Code::ComputeFlags(Code::KEYED_STORE_IC, state, strict_mode_, type); |
| 1687 MaybeObject* result = GetCodeWithFlags(flags, name); | 1546 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1688 if (!result->IsFailure()) { | 1547 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); |
| 1689 PROFILE(isolate(), | 1548 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); |
| 1690 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, | 1549 return code; |
| 1691 Code::cast(result->ToObjectUnchecked()), | |
| 1692 name)); | |
| 1693 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, | |
| 1694 name, | |
| 1695 Code::cast(result->ToObjectUnchecked()))); | |
| 1696 } | |
| 1697 return result; | |
| 1698 } | 1550 } |
| 1699 | 1551 |
| 1700 | 1552 |
| 1701 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1553 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( |
| 1702 MacroAssembler* masm) { | 1554 MacroAssembler* masm) { |
| 1703 KeyedStoreIC::GenerateSlow(masm); | 1555 KeyedStoreIC::GenerateSlow(masm); |
| 1704 } | 1556 } |
| 1705 | 1557 |
| 1706 | 1558 |
| 1707 CallStubCompiler::CallStubCompiler(int argc, | 1559 CallStubCompiler::CallStubCompiler(Isolate* isolate, |
| 1560 int argc, |
| 1708 Code::Kind kind, | 1561 Code::Kind kind, |
| 1709 Code::ExtraICState extra_ic_state, | 1562 Code::ExtraICState extra_state, |
| 1710 InlineCacheHolderFlag cache_holder) | 1563 InlineCacheHolderFlag cache_holder) |
| 1711 : arguments_(argc), | 1564 : StubCompiler(isolate), |
| 1565 arguments_(argc), |
| 1712 kind_(kind), | 1566 kind_(kind), |
| 1713 extra_ic_state_(extra_ic_state), | 1567 extra_state_(extra_state), |
| 1714 cache_holder_(cache_holder) { | 1568 cache_holder_(cache_holder) { |
| 1715 } | 1569 } |
| 1716 | 1570 |
| 1717 | 1571 |
| 1718 bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) { | 1572 bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) { |
| 1719 SharedFunctionInfo* info = function->shared(); | 1573 SharedFunctionInfo* info = function->shared(); |
| 1720 if (info->HasBuiltinFunctionId()) { | 1574 if (info->HasBuiltinFunctionId()) { |
| 1721 BuiltinFunctionId id = info->builtin_function_id(); | 1575 BuiltinFunctionId id = info->builtin_function_id(); |
| 1722 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true; | 1576 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true; |
| 1723 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1577 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1756 ASSERT(optimization.is_simple_api_call()); | 1610 ASSERT(optimization.is_simple_api_call()); |
| 1757 return CompileFastApiCall(optimization, | 1611 return CompileFastApiCall(optimization, |
| 1758 object, | 1612 object, |
| 1759 holder, | 1613 holder, |
| 1760 cell, | 1614 cell, |
| 1761 function, | 1615 function, |
| 1762 fname); | 1616 fname); |
| 1763 } | 1617 } |
| 1764 | 1618 |
| 1765 | 1619 |
| 1766 MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) { | 1620 Handle<Code> CallStubCompiler::GetCode(PropertyType type, Handle<String> name) { |
| 1767 int argc = arguments_.immediate(); | 1621 int argc = arguments_.immediate(); |
| 1768 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, | 1622 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, |
| 1769 type, | 1623 type, |
| 1770 extra_ic_state_, | 1624 extra_state_, |
| 1771 cache_holder_, | 1625 cache_holder_, |
| 1772 argc); | 1626 argc); |
| 1773 return GetCodeWithFlags(flags, name); | 1627 return GetCodeWithFlags(flags, name); |
| 1774 } | 1628 } |
| 1775 | 1629 |
| 1776 | 1630 |
| 1777 MaybeObject* CallStubCompiler::GetCode(JSFunction* function) { | 1631 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { |
| 1632 Handle<String> function_name; |
| 1633 if (function->shared()->name()->IsString()) { |
| 1634 function_name = Handle<String>(String::cast(function->shared()->name())); |
| 1635 } |
| 1636 return GetCode(CONSTANT_FUNCTION, function_name); |
| 1637 } |
| 1638 |
| 1639 |
| 1640 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1641 // handlified. |
| 1642 MaybeObject* CallStubCompiler::TryGetCode(PropertyType type, String* name) { |
| 1643 int argc = arguments_.immediate(); |
| 1644 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, |
| 1645 type, |
| 1646 extra_state_, |
| 1647 cache_holder_, |
| 1648 argc); |
| 1649 return TryGetCodeWithFlags(flags, name); |
| 1650 } |
| 1651 |
| 1652 |
| 1653 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1654 // handlified. |
| 1655 MaybeObject* CallStubCompiler::TryGetCode(JSFunction* function) { |
| 1778 String* function_name = NULL; | 1656 String* function_name = NULL; |
| 1779 if (function->shared()->name()->IsString()) { | 1657 if (function->shared()->name()->IsString()) { |
| 1780 function_name = String::cast(function->shared()->name()); | 1658 function_name = String::cast(function->shared()->name()); |
| 1781 } | 1659 } |
| 1782 return GetCode(CONSTANT_FUNCTION, function_name); | 1660 return TryGetCode(CONSTANT_FUNCTION, function_name); |
| 1783 } | 1661 } |
| 1784 | 1662 |
| 1785 | 1663 |
| 1786 MaybeObject* ConstructStubCompiler::GetCode() { | 1664 MaybeObject* ConstructStubCompiler::GetCode() { |
| 1787 Code::Flags flags = Code::ComputeFlags(Code::STUB); | 1665 Code::Flags flags = Code::ComputeFlags(Code::STUB); |
| 1788 Object* result; | 1666 Object* result; |
| 1789 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub"); | 1667 { MaybeObject* maybe_result = TryGetCodeWithFlags(flags, "ConstructStub"); |
| 1790 if (!maybe_result->ToObject(&result)) return maybe_result; | 1668 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1791 } | 1669 } |
| 1792 Code* code = Code::cast(result); | 1670 Code* code = Code::cast(result); |
| 1793 USE(code); | 1671 USE(code); |
| 1794 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub")); | 1672 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub")); |
| 1795 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code))); | 1673 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code))); |
| 1796 return result; | 1674 return result; |
| 1797 } | 1675 } |
| 1798 | 1676 |
| 1799 | 1677 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 expected_receiver_type_ = | 1736 expected_receiver_type_ = |
| 1859 FunctionTemplateInfo::cast(signature->receiver()); | 1737 FunctionTemplateInfo::cast(signature->receiver()); |
| 1860 } | 1738 } |
| 1861 } | 1739 } |
| 1862 | 1740 |
| 1863 is_simple_api_call_ = true; | 1741 is_simple_api_call_ = true; |
| 1864 } | 1742 } |
| 1865 | 1743 |
| 1866 | 1744 |
| 1867 } } // namespace v8::internal | 1745 } } // namespace v8::internal |
| OLD | NEW |