| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 22 matching lines...) Expand all Loading... |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "stub-cache.h" | 34 #include "stub-cache.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 | 39 |
| 40 #define __ ACCESS_MASM(masm) | 40 #define __ ACCESS_MASM(masm) |
| 41 | 41 |
| 42 | 42 |
| 43 // Helper function used to check that the dictionary doesn't contain | 43 void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 44 // the property. This function may return false negatives, so miss_label | 44 Label* miss_label, |
| 45 // must always call a backup property check that is complete. | 45 Register receiver, |
| 46 // This function is safe to call if the receiver has fast properties. | 46 Handle<Name> name, |
| 47 // Name must be unique and receiver must be a heap object. | 47 Register scratch0, |
| 48 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 48 Register scratch1) { |
| 49 Label* miss_label, | 49 ASSERT(!AreAliased(receiver, scratch0, scratch1)); |
| 50 Register receiver, | |
| 51 Handle<Name> name, | |
| 52 Register scratch0, | |
| 53 Register scratch1) { | |
| 54 ASSERT(!AreAliased(scratch0, scratch1)); | |
| 55 ASSERT(name->IsUniqueName()); | 50 ASSERT(name->IsUniqueName()); |
| 56 Counters* counters = masm->isolate()->counters(); | 51 Counters* counters = masm->isolate()->counters(); |
| 57 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 52 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
| 58 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 53 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 59 | 54 |
| 60 Label done; | 55 Label done; |
| 61 | 56 |
| 62 const int kInterceptorOrAccessCheckNeededMask = | 57 const int kInterceptorOrAccessCheckNeededMask = |
| 63 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 58 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 64 | 59 |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly | 366 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly |
| 372 // move the result in x0. | 367 // move the result in x0. |
| 373 __ Mov(x0, scratch1); | 368 __ Mov(x0, scratch1); |
| 374 __ Ret(); | 369 __ Ret(); |
| 375 } | 370 } |
| 376 | 371 |
| 377 | 372 |
| 378 // Generate code to check that a global property cell is empty. Create | 373 // Generate code to check that a global property cell is empty. Create |
| 379 // the property cell at compilation time if no cell exists for the | 374 // the property cell at compilation time if no cell exists for the |
| 380 // property. | 375 // property. |
| 381 static void GenerateCheckPropertyCell(MacroAssembler* masm, | 376 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, |
| 382 Handle<GlobalObject> global, | 377 Handle<JSGlobalObject> global, |
| 383 Handle<Name> name, | 378 Handle<Name> name, |
| 384 Register scratch, | 379 Register scratch, |
| 385 Register the_hole, | 380 Label* miss) { |
| 386 Label* miss) { | 381 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
| 387 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name); | |
| 388 ASSERT(cell->value()->IsTheHole()); | 382 ASSERT(cell->value()->IsTheHole()); |
| 389 __ Mov(scratch, Operand(cell)); | 383 __ Mov(scratch, Operand(cell)); |
| 390 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 384 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
| 391 __ Cmp(scratch, the_hole); | 385 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); |
| 392 __ B(ne, miss); | |
| 393 } | 386 } |
| 394 | 387 |
| 395 | 388 |
| 396 void StoreStubCompiler::GenerateNegativeHolderLookup( | 389 void StoreStubCompiler::GenerateNegativeHolderLookup( |
| 397 MacroAssembler* masm, | 390 MacroAssembler* masm, |
| 398 Handle<JSObject> holder, | 391 Handle<JSObject> holder, |
| 399 Register holder_reg, | 392 Register holder_reg, |
| 400 Handle<Name> name, | 393 Handle<Name> name, |
| 401 Label* miss) { | 394 Label* miss) { |
| 402 if (holder->IsJSGlobalObject()) { | 395 if (holder->IsJSGlobalObject()) { |
| 403 __ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex); | |
| 404 GenerateCheckPropertyCell( | 396 GenerateCheckPropertyCell( |
| 405 masm, Handle<GlobalObject>::cast(holder), name, | 397 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
| 406 scratch1(), scratch2(), miss); | |
| 407 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 398 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 408 GenerateDictionaryNegativeLookup( | 399 GenerateDictionaryNegativeLookup( |
| 409 masm, miss, holder_reg, name, scratch1(), scratch2()); | 400 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 410 } | 401 } |
| 411 } | 402 } |
| 412 | 403 |
| 413 | 404 |
| 414 // Generate StoreTransition code, value is passed in x0 register. | 405 // Generate StoreTransition code, value is passed in x0 register. |
| 415 // When leaving generated code after success, the receiver_reg and storage_reg | 406 // When leaving generated code after success, the receiver_reg and storage_reg |
| 416 // may be clobbered. Upon branch to miss_label, the receiver and name registers | 407 // may be clobbered. Upon branch to miss_label, the receiver and name registers |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 697 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 707 Label* label, | 698 Label* label, |
| 708 Handle<Name> name) { | 699 Handle<Name> name) { |
| 709 if (!label->is_unused()) { | 700 if (!label->is_unused()) { |
| 710 __ Bind(label); | 701 __ Bind(label); |
| 711 __ Mov(this->name(), Operand(name)); | 702 __ Mov(this->name(), Operand(name)); |
| 712 } | 703 } |
| 713 } | 704 } |
| 714 | 705 |
| 715 | 706 |
| 716 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 707 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, |
| 717 // from object to (but not including) holder. | 708 Handle<JSObject> object, |
| 718 static void GenerateCheckPropertyCells(MacroAssembler* masm, | 709 Handle<JSObject> holder, |
| 719 Handle<JSObject> object, | 710 Handle<Name> name, |
| 720 Handle<JSObject> holder, | 711 Register scratch1, |
| 721 Handle<Name> name, | 712 Label* miss) { |
| 722 Register scratch1, | |
| 723 Register scratch2, | |
| 724 Label* miss) { | |
| 725 bool the_hole_is_loaded = false; | |
| 726 Handle<JSObject> current = object; | 713 Handle<JSObject> current = object; |
| 727 while (!current.is_identical_to(holder)) { | 714 while (!current.is_identical_to(holder)) { |
| 728 if (current->IsGlobalObject()) { | 715 if (current->IsJSGlobalObject()) { |
| 729 if (!the_hole_is_loaded) { | 716 // TODO(all): GenerateCheckPropertyCell loads the hole (root value) every |
| 730 __ LoadRoot(scratch2, Heap::kTheHoleValueRootIndex); | 717 // time. Hoist that out, and load it once at the start. |
| 731 the_hole_is_loaded = true; | |
| 732 } | |
| 733 GenerateCheckPropertyCell(masm, | 718 GenerateCheckPropertyCell(masm, |
| 734 Handle<GlobalObject>::cast(current), | 719 Handle<JSGlobalObject>::cast(current), |
| 735 name, | 720 name, |
| 736 scratch1, | 721 scratch1, |
| 737 scratch2, | |
| 738 miss); | 722 miss); |
| 739 } | 723 } |
| 740 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 724 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 741 } | 725 } |
| 742 } | 726 } |
| 743 | 727 |
| 744 | 728 |
| 745 // The function to called must be passed in x1. | 729 // The function to called must be passed in x1. |
| 746 static void GenerateCallFunction(MacroAssembler* masm, | 730 static void GenerateCallFunction(MacroAssembler* masm, |
| 747 Handle<Object> object, | 731 Handle<Object> object, |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1288 | 1272 |
| 1289 // Perform security check for access to the global object. | 1273 // Perform security check for access to the global object. |
| 1290 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1274 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1291 if (holder->IsJSGlobalProxy()) { | 1275 if (holder->IsJSGlobalProxy()) { |
| 1292 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1276 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1293 } | 1277 } |
| 1294 | 1278 |
| 1295 // If we've skipped any global objects, it's not enough to verify that | 1279 // If we've skipped any global objects, it's not enough to verify that |
| 1296 // their maps haven't changed. We also need to check that the property | 1280 // their maps haven't changed. We also need to check that the property |
| 1297 // cell for the property is still empty. | 1281 // cell for the property is still empty. |
| 1298 GenerateCheckPropertyCells(masm(), object, holder, name, | 1282 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1299 scratch1, scratch2, miss); | |
| 1300 | 1283 |
| 1301 // Return the register containing the holder. | 1284 // Return the register containing the holder. |
| 1302 return reg; | 1285 return reg; |
| 1303 } | 1286 } |
| 1304 | 1287 |
| 1305 | 1288 |
| 1306 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, | 1289 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
| 1307 Label* success, | 1290 Label* success, |
| 1308 Label* miss) { | 1291 Label* miss) { |
| 1309 if (!miss->is_unused()) { | 1292 if (!miss->is_unused()) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1366 __ Ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 1349 __ Ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
| 1367 __ Cmp(scratch2(), Operand(callback)); | 1350 __ Cmp(scratch2(), Operand(callback)); |
| 1368 __ B(ne, &miss); | 1351 __ B(ne, &miss); |
| 1369 } | 1352 } |
| 1370 | 1353 |
| 1371 HandlerFrontendFooter(name, success, &miss); | 1354 HandlerFrontendFooter(name, success, &miss); |
| 1372 return reg; | 1355 return reg; |
| 1373 } | 1356 } |
| 1374 | 1357 |
| 1375 | 1358 |
| 1376 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<JSObject> object, | |
| 1377 Handle<JSObject> last, | |
| 1378 Handle<Name> name, | |
| 1379 Label* success, | |
| 1380 Handle<GlobalObject> global) { | |
| 1381 Label miss; | |
| 1382 | |
| 1383 HandlerFrontendHeader(object, receiver(), last, name, &miss); | |
| 1384 | |
| 1385 // If the last object in the prototype chain is a global object, | |
| 1386 // check that the global property cell is empty. | |
| 1387 if (!global.is_null()) { | |
| 1388 GenerateCheckPropertyCell(masm(), global, name, | |
| 1389 scratch1(), scratch2(), &miss); | |
| 1390 } | |
| 1391 | |
| 1392 HandlerFrontendFooter(name, success, &miss); | |
| 1393 } | |
| 1394 | |
| 1395 | |
| 1396 void LoadStubCompiler::GenerateLoadField(Register reg, | 1359 void LoadStubCompiler::GenerateLoadField(Register reg, |
| 1397 Handle<JSObject> holder, | 1360 Handle<JSObject> holder, |
| 1398 PropertyIndex field, | 1361 PropertyIndex field, |
| 1399 Representation representation) { | 1362 Representation representation) { |
| 1400 __ Mov(receiver(), reg); | 1363 __ Mov(receiver(), reg); |
| 1401 if (kind() == Code::LOAD_IC) { | 1364 if (kind() == Code::LOAD_IC) { |
| 1402 LoadFieldStub stub(field.is_inobject(holder), | 1365 LoadFieldStub stub(field.is_inobject(holder), |
| 1403 field.translate(holder), | 1366 field.translate(holder), |
| 1404 representation); | 1367 representation); |
| 1405 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1368 GenerateTailCall(masm(), stub.GetCode(isolate())); |
| (...skipping 1592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2998 | 2961 |
| 2999 // Return the generated code. | 2962 // Return the generated code. |
| 3000 return GetCode(kind(), Code::INTERCEPTOR, name); | 2963 return GetCode(kind(), Code::INTERCEPTOR, name); |
| 3001 } | 2964 } |
| 3002 | 2965 |
| 3003 | 2966 |
| 3004 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2967 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( |
| 3005 Handle<JSObject> object, | 2968 Handle<JSObject> object, |
| 3006 Handle<JSObject> last, | 2969 Handle<JSObject> last, |
| 3007 Handle<Name> name, | 2970 Handle<Name> name, |
| 3008 Handle<GlobalObject> global) { | 2971 Handle<JSGlobalObject> global) { |
| 3009 Label success; | 2972 Label success; |
| 3010 NonexistentHandlerFrontend(object, last, name, &success, global); | 2973 NonexistentHandlerFrontend(object, last, name, &success, global); |
| 3011 | 2974 |
| 3012 __ Bind(&success); | 2975 __ Bind(&success); |
| 3013 // Return undefined if maps of the full prototype chain are still the | 2976 // Return undefined if maps of the full prototype chain are still the |
| 3014 // same and no global property with this name contains a value. | 2977 // same and no global property with this name contains a value. |
| 3015 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 2978 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 3016 __ Ret(); | 2979 __ Ret(); |
| 3017 | 2980 |
| 3018 // Return the generated code. | 2981 // Return the generated code. |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3265 | 3228 |
| 3266 // Miss case, call the runtime. | 3229 // Miss case, call the runtime. |
| 3267 __ Bind(&miss_force_generic); | 3230 __ Bind(&miss_force_generic); |
| 3268 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); | 3231 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3269 } | 3232 } |
| 3270 | 3233 |
| 3271 | 3234 |
| 3272 } } // namespace v8::internal | 3235 } } // namespace v8::internal |
| 3273 | 3236 |
| 3274 #endif // V8_TARGET_ARCH_A64 | 3237 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |