Changeset 263523 in webkit
- Timestamp:
- Jun 25, 2020, 12:32:34 PM (5 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r263497 r263523 1 2020-06-25 Mark Lam <mark.lam@apple.com> 2 3 JSCell constructor needs to ensure that the passed in structure is still alive. 4 https://bugs.webkit.org/show_bug.cgi?id=213593 5 <rdar://problem/64597573> 6 7 Reviewed by Yusuke Suzuki. 8 9 Note that in the initializer list of the `JSCell(VM&, Structure*)` constructor, 10 we are only using values inside the passed in structure but not necessarily the 11 structure pointer itself. All these values are contained inside Structure::m_blob. 12 Note also that this constructor is an inline function. Hence, the compiler may 13 choose to pre-compute the address of structure->m_blob and discard the structure 14 pointer itself. 15 16 Here's an example: 17 18 0x10317a21e <+1054>: movq 0x18(%rsp), %rdx // rdx:vm = &vm 19 0x10317a223 <+1059>: addq $0x8, %r13 // r13 = &structure.m_blob <== pre-compute address of m_blob !!! 20 // r13 previously contained the structure pointer. 21 // Now, there's no more references to the structure base address. 22 23 0x10317a227 <+1063>: leaq 0x48(%rdx), %rdi // arg0:heap = &vm.heap 24 0x10317a22b <+1067>: movl $0x10, %edx // arg2:size = 16. 25 0x10317a230 <+1072>: movq %rdi, 0x28(%rsp) 26 0x10317a235 <+1077>: xorl %esi, %esi // arg1:deferralContext = 0 27 0x10317a237 <+1079>: callq 0x10317ae60 // call JSC::allocateCell<JSC::JSArray> <== Can GC here !!! 28 29 0x10317a23c <+1084>: movq %rax, %rbx // rbx:cell = rax:allocation result. 30 ... 31 0x10317a253 <+1107>: movl (%r13), %eax // eax = m_blob.structureID <== Use pre-computed m_blob address here. 32 33 There's a chance that the GC may run while allocating this cell. In the event 34 that the structure is newly instantiated just before calling this constructor, 35 there may not be any other references to it. As a result, the structure may get 36 collected before the cell is even constructed. To avoid this possibility, we need 37 to ensure that the structure pointer is still alive by the time this constructor 38 is called. 39 40 I am not committing any tests for this issue because the test cases relies on: 41 42 1. Manually forcing an O3 ASan Release build. 43 44 2. Not running jsc with --useDollarVM=1. Note: the JSC test harness automatically 45 adds --useDollarVM=1 for all test runs. 46 47 3. Memory being allocated in a specific order. The recent Bitmap FreeList change 48 enabled this issue to manifest. The old linked list FreeList implementation 49 would have hidden the issue. 50 51 4. Adding some logging code can also make the issue stop manifesting. 52 53 In short, the test cases will not detect any regression even if we commit them 54 because the existing automatic regression test runs will not have the necessary 55 conditions for reproducing the issue. The tests are also somewhat fragile where 56 any changes in memory layout may stop the issue from manifesting in an observable 57 way. 58 59 * runtime/JSCellInlines.h: 60 (JSC::JSCell::JSCell): 61 1 62 2020-06-24 Ross Kirsling <ross.kirsling@sony.com> 2 63 -
trunk/Source/JavaScriptCore/runtime/JSCellInlines.h
r260984 r263523 1 1 /* 2 * Copyright (C) 2012-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2012-2020 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 64 64 { 65 65 ASSERT(!isCompilationThread()); 66 67 // Note that in the constructor initializer list above, we are only using values 68 // inside structure but not necessarily the structure pointer itself. All these 69 // values are contained inside Structure::m_blob. Note also that this constructor 70 // is an inline function. Hence, the compiler may choose to pre-compute the address 71 // of structure->m_blob and discard the structure pointer itself. There's a chance 72 // that the GC may run while allocating this cell. In the event that the structure 73 // is newly instantiated just before calling this constructor, there may not be any 74 // other references to it. As a result, the structure may get collected before this 75 // cell is even constructed. To avoid this possibility, we need to ensure that the 76 // structure pointer is still alive at this point. 77 ensureStillAliveHere(structure); 66 78 } 67 79
Note:
See TracChangeset
for help on using the changeset viewer.