| 2236 | } |
| 2237 | |
| 2238 | Object::FieldType *Object::FindField(name_t name, index_t &insert_pos) |
| 2239 | { |
| 2240 | index_t left = 0, mid, right = mFields.Length(); |
| 2241 | int first_char = *name; |
| 2242 | if (first_char <= 'Z' && first_char >= 'A') |
| 2243 | first_char += 32; |
| 2244 | while (left < right) |
| 2245 | { |
| 2246 | mid = left + ((right - left) >> 1); |
| 2247 | |
| 2248 | FieldType &field = mFields[mid]; |
| 2249 | |
| 2250 | // key_c contains the lower-case version of field.name[0]. Checking key_c first |
| 2251 | // allows the _tcsicmp() call to be skipped whenever the first character differs. |
| 2252 | // This also means that .name isn't dereferenced, which means one less potential |
| 2253 | // CPU cache miss (where we wait for the data to be pulled from RAM into cache). |
| 2254 | // field.key_c might cause a cache miss, but it's very likely that key.s will be |
| 2255 | // read into cache at the same time (but only the pointer value, not the chars). |
| 2256 | int result = first_char - field.key_c; |
| 2257 | if (!result) |
| 2258 | result = _tcsicmp(name, field.name); |
| 2259 | |
| 2260 | if (result < 0) |
| 2261 | right = mid; |
| 2262 | else if (result > 0) |
| 2263 | left = mid + 1; |
| 2264 | else |
| 2265 | return &field; |
| 2266 | } |
| 2267 | insert_pos = left; |
| 2268 | return nullptr; |
| 2269 | } |
| 2270 | |
| 2271 | bool Object::HasProp(name_t name) |
| 2272 | { |