this repo has no description
at trunk 4741 lines 171 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "runtime.h" 3 4#include <unistd.h> 5 6#include <cinttypes> 7#include <climits> 8#include <csignal> 9#include <cstdarg> 10#include <cstdio> 11#include <cstdlib> 12#include <cstring> 13#include <cwchar> 14#include <fstream> 15#include <memory> 16 17#include "array-module.h" 18#include "attributedict.h" 19#include "builtins-module.h" 20#include "bytearray-builtins.h" 21#include "bytecode.h" 22#include "bytes-builtins.h" 23#include "byteslike.h" 24#include "capi.h" 25#include "code-builtins.h" 26#include "complex-builtins.h" 27#include "descriptor-builtins.h" 28#include "dict-builtins.h" 29#include "event.h" 30#include "exception-builtins.h" 31#include "file.h" 32#include "float-builtins.h" 33#include "formatter-utils.h" 34#include "frame-proxy-builtins.h" 35#include "frame.h" 36#include "function-builtins.h" 37#include "generator-builtins.h" 38#include "globals.h" 39#include "handles.h" 40#include "heap.h" 41#include "int-builtins.h" 42#include "interpreter.h" 43#include "iterator-builtins.h" 44#include "layout-builtins.h" 45#include "layout.h" 46#include "list-builtins.h" 47#include "mappingproxy-builtins.h" 48#include "memoryview-builtins.h" 49#include "mmap-module.h" 50#include "module-builtins.h" 51#include "module-proxy-builtins.h" 52#include "modules.h" 53#include "mutex.h" 54#include "object-builtins.h" 55#include "os.h" 56#include "range-builtins.h" 57#include "ref-builtins.h" 58#include "scavenger.h" 59#include "set-builtins.h" 60#include "siphash.h" 61#include "slice-builtins.h" 62#include "str-builtins.h" 63#include "str-intern.h" 64#include "strarray-builtins.h" 65#include "super-builtins.h" 66#include "sys-module.h" 67#include "thread.h" 68#include "traceback-builtins.h" 69#include "tuple-builtins.h" 70#include "type-builtins.h" 71#include "under-collections-module.h" 72#include "under-contextvars-module.h" 73#include "under-io-module.h" 74#include "under-signal-module.h" 75#include "unicode.h" 76#include "utils.h" 77#include "valuecell-builtins.h" 78#include "visitor.h" 79 80namespace py { 81 82static const SymbolId kRequiredModules[] = { 83 ID(_builtins), ID(builtins), ID(operator), 84 ID(_codecs), ID(_signal), ID(_frozen_importlib_external)}; 85 86word Runtime::next_module_index_ = 0; 87 88wchar_t Runtime::exec_prefix_[PATH_MAX + 1] = L""; 89wchar_t Runtime::module_search_path_[PATH_MAX + 1] = L""; 90wchar_t Runtime::prefix_[PATH_MAX + 1] = L""; 91wchar_t Runtime::program_name_[NAME_MAX + 1] = L"python3"; 92 93wchar_t* Runtime::programName() { return program_name_; } 94 95void Runtime::setExecPrefix(const wchar_t* exec_prefix) { 96 DCHECK(wcslen(exec_prefix) < ARRAYSIZE(exec_prefix_), 97 "exec_prefix is too long"); 98 std::wcsncpy(exec_prefix_, exec_prefix, ARRAYSIZE(exec_prefix_)); 99 exec_prefix_[ARRAYSIZE(exec_prefix_) - 1] = L'\0'; 100} 101 102void Runtime::setModuleSearchPath(const wchar_t* module_search_path) { 103 DCHECK(wcslen(module_search_path) < ARRAYSIZE(module_search_path_), 104 "module_search_path is too long"); 105 std::wcsncpy(module_search_path_, module_search_path, 106 ARRAYSIZE(module_search_path_)); 107 module_search_path_[ARRAYSIZE(module_search_path_) - 1] = L'\0'; 108} 109 110void Runtime::setPrefix(const wchar_t* prefix) { 111 DCHECK(wcslen(prefix) < ARRAYSIZE(module_search_path_), "prefix is too long"); 112 std::wcsncpy(prefix_, prefix, ARRAYSIZE(prefix_)); 113 prefix_[ARRAYSIZE(prefix_) - 1] = L'\0'; 114} 115 116void Runtime::setProgramName(const wchar_t* program_name) { 117 DCHECK(wcslen(program_name) < ARRAYSIZE(program_name_), 118 "program_name is too long"); 119 std::wcsncpy(program_name_, program_name, ARRAYSIZE(program_name_)); 120 prefix_[ARRAYSIZE(program_name_) - 1] = L'\0'; 121} 122 123RandomState randomState() { 124 RandomState result; 125 OS::secureRandom(reinterpret_cast<byte*>(&result), sizeof(result)); 126 return result; 127} 128 129RandomState randomStateFromSeed(uint64_t seed) { 130 // Splitmix64 as suggested by http://xoshiro.di.unimi.it. 131 auto next = [&seed]() { 132 uint64_t z = (seed += 0x9e3779b97f4a7c15); 133 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; 134 z = (z ^ (z >> 27)) * 0x94d049bb133111eb; 135 return z ^ (z >> 31); 136 }; 137 RandomState result; 138 for (size_t i = 0; i < ARRAYSIZE(result.state); i++) { 139 result.state[i] = next(); 140 } 141 result.siphash24_secret = next(); 142 for (size_t i = 0; i < ARRAYSIZE(result.extra_secret); i++) { 143 result.extra_secret[i] = next(); 144 } 145 return result; 146} 147 148Runtime::Runtime(word heap_size, Interpreter* interpreter, 149 RandomState random_seed, StdioState stdio_state) 150 : heap_(heap_size), 151 interpreter_(interpreter), 152 random_state_(random_seed), 153 stdio_state_(stdio_state) { 154 Thread* thread = newThread(); 155 thread->begin(); 156 // This must be called before initializeTypes is called. Methods in 157 // initializeTypes rely on instances that are created in this method. 158 initializePrimitiveInstances(); 159 initializeInterned(thread); 160 initializeSymbols(thread); 161 initializeLayouts(); 162 initializeTypes(thread); 163 initializeCAPIState(this); 164 initializeModules(thread); 165 initializeCAPIModules(); 166 initializeJITState(); 167 168 // This creates a reference that prevents the linker from garbage collecting 169 // all of the symbols in debugging.cpp. This is a temporary workaround until 170 // we can fix the build to prevent symbols in debugging.cpp from being GCed. 171 extern void initializeDebugging(); 172 initializeDebugging(); 173} 174 175Runtime::~Runtime() { 176 is_finalizing_ = true; 177 // TODO(T30392425): This is an ugly and fragile workaround for having multiple 178 // runtimes created and destroyed by a single thread. 179 if (Thread::current() == nullptr) { 180 CHECK(main_thread_ != nullptr, "the runtime does not have any threads"); 181 Thread::setCurrentThread(main_thread_); 182 } 183 callAtExit(); 184 flushStdFiles(); 185 finalizeSignals(Thread::current()); 186 clearHandleScopes(); 187 finalizeCAPIModules(); 188 freeApiHandles(); 189 finalizeCAPIState(this); 190 { 191 MutexGuard lock(&threads_mutex_); 192 Thread* thread = main_thread_; 193 Thread::setCurrentThread(nullptr); 194 main_thread_ = nullptr; 195 for (Thread* next; thread != nullptr; thread = next) { 196 next = thread->next(); 197 delete thread; 198 } 199 } 200 delete symbols_; 201 delete machine_code_; 202} 203 204bool Runtime::allocateForMachineCode(word size, uword* address_out) { 205 DCHECK(Utils::isAligned(size, kPointerSize), "request %ld not aligned", size); 206 if (UNLIKELY(!machine_code_->allocate(size, address_out))) { 207 UNIMPLEMENTED("out of fixed memory"); 208 } 209 return true; 210} 211 212RawObject Runtime::newBoundMethod(const Object& function, const Object& self) { 213 HandleScope scope(Thread::current()); 214 BoundMethod bound_method( 215 &scope, newInstanceWithSize(LayoutId::kBoundMethod, BoundMethod::kSize)); 216 bound_method.setFunction(*function); 217 bound_method.setSelf(*self); 218 return *bound_method; 219} 220 221RawObject Runtime::newLayout(LayoutId id) { 222 HandleScope scope(Thread::current()); 223 Layout layout(&scope, newInstanceWithSize(LayoutId::kLayout, Layout::kSize)); 224 layout.setId(id); 225 layout.setInObjectAttributes(empty_tuple_); 226 layout.setAdditions(newList()); 227 layout.setDeletions(newList()); 228 layout.setNumInObjectAttributes(0); 229 return *layout; 230} 231 232RawObject Runtime::layoutAtSafe(LayoutId layout_id) { 233 word id = static_cast<word>(layout_id); 234 if (id < 0 || id >= num_layouts_) { 235 return Error::notFound(); 236 } 237 RawObject result = Tuple::cast(layouts_).at(id); 238 if (result == SmallInt::fromWord(0)) return Error::notFound(); 239 return result; 240} 241 242// Sanity check that a subclass that has fixed attributes does inherit from a 243// superclass with attributes that are fixed. 244static void checkInObjectAttributesWithFixedOffset(const Tuple& attributes) { 245 for (word i = 0; i < attributes.length(); i++) { 246 AttributeInfo info(Tuple::cast(attributes.at(i)).at(1)); 247 CHECK(info.isInObject() && info.isFixedOffset(), 248 "all superclass attributes must be in-object and fixed"); 249 } 250} 251 252RawObject Runtime::layoutCreateSubclassWithBuiltins( 253 Thread* thread, LayoutId subclass_id, LayoutId superclass_id, 254 View<BuiltinAttribute> attributes, word size) { 255 HandleScope scope(thread); 256 257 // A builtin class is special since it contains attributes that must be 258 // located at fixed offsets from the start of an instance. These attributes 259 // are packed at the beginning of the layout starting at offset 0. 260 Layout super_layout(&scope, layoutAt(superclass_id)); 261 Tuple super_attributes(&scope, super_layout.inObjectAttributes()); 262 checkInObjectAttributesWithFixedOffset(super_attributes); 263 264 word super_attributes_len = super_attributes.length(); 265 word attributes_length = attributes.length(); 266 CHECK((attributes_length + super_attributes_len) * kPointerSize == size, 267 "Object size does not match attribute count"); 268 for (word i = 0; i < attributes_length; i++) { 269 CHECK(attributes.get(i).offset == (i + super_attributes_len) * kPointerSize, 270 "unexpected attribute offset (not sorted or duplicated?)"); 271 } 272 273 // Create an empty layout for the subclass 274 Layout result(&scope, newLayout(subclass_id)); 275 276 // Copy down all of the superclass attributes into the subclass layout 277 result.setOverflowAttributes(super_layout.overflowAttributes()); 278 word in_object_len = super_attributes_len + attributes_length; 279 if (in_object_len == 0) { 280 result.setInObjectAttributes(emptyTuple()); 281 result.setNumInObjectAttributes(0); 282 } else { 283 MutableTuple in_object(&scope, newMutableTuple(in_object_len)); 284 in_object.replaceFromWith(0, *super_attributes, super_attributes_len); 285 appendBuiltinAttributes(thread, attributes, in_object, 286 super_attributes_len); 287 288 // Install the in-object attributes 289 result.setInObjectAttributes(in_object.becomeImmutable()); 290 result.setNumInObjectAttributes(in_object_len); 291 } 292 293 return *result; 294} 295 296void Runtime::appendBuiltinAttributes(Thread* thread, 297 View<BuiltinAttribute> attributes, 298 const MutableTuple& dst, 299 word start_index) { 300 if (attributes.length() == 0) { 301 return; 302 } 303 HandleScope scope(thread); 304 Object name(&scope, NoneType::object()); 305 for (word i = 0; i < attributes.length(); i++) { 306 DCHECK((attributes.get(i).flags & 307 (AttributeFlags::kInObject | AttributeFlags::kDeleted | 308 AttributeFlags::kFixedOffset)) == 0, 309 "flag not allowed"); 310 AttributeInfo info(attributes.get(i).offset, 311 attributes.get(i).flags | AttributeFlags::kInObject | 312 AttributeFlags::kFixedOffset); 313 SymbolId symbol_id = attributes.get(i).name; 314 name = symbol_id == SymbolId::kInvalid 315 ? NoneType::object() 316 : static_cast<RawObject>(symbols()->at(symbol_id)); 317 dst.atPut(start_index + i, layoutNewAttribute(name, info)); 318 } 319} 320 321RawObject Runtime::newBytearray() { 322 HandleScope scope(Thread::current()); 323 Bytearray result(&scope, 324 newInstanceWithSize(LayoutId::kBytearray, Bytearray::kSize)); 325 result.setItems(empty_mutable_bytes_); 326 result.setNumItems(0); 327 return *result; 328} 329 330RawObject Runtime::newBytearrayIterator(Thread* thread, 331 const Bytearray& bytearray) { 332 HandleScope scope(thread); 333 BytearrayIterator result(&scope, 334 newInstanceWithSize(LayoutId::kBytearrayIterator, 335 BytearrayIterator::kSize)); 336 result.setIterable(*bytearray); 337 result.setIndex(0); 338 return *result; 339} 340 341RawObject Runtime::createLargeBytes(word length) { 342 DCHECK(length > SmallBytes::kMaxLength, "fits into a SmallBytes"); 343 word size = LargeBytes::allocationSize(length); 344 uword address; 345 CHECK(heap()->allocate(size, &address), "out of memory"); 346 return LargeBytes::cast( 347 DataArray::initialize(address, length, LayoutId::kLargeBytes)); 348} 349 350RawObject Runtime::createLargeInt(word num_digits) { 351 DCHECK(num_digits > 0, "num_digits must be positive"); 352 word size = LargeInt::allocationSize(num_digits); 353 uword address; 354 CHECK(heap()->allocate(size, &address), "out of memory"); 355 return LargeInt::cast(LargeInt::initialize(address, num_digits)); 356} 357 358RawObject Runtime::createLargeStr(word length) { 359 DCHECK(length > RawSmallStr::kMaxLength, 360 "string len %ld is too small to be a large string", length); 361 word size = LargeStr::allocationSize(length); 362 uword address; 363 CHECK(heap()->allocate(size, &address), "out of memory"); 364 return LargeStr::cast( 365 DataArray::initialize(address, length, LayoutId::kLargeStr)); 366} 367 368RawObject Runtime::createMutableBytes(word length) { 369 DCHECK(length >= 0, "cannot allocate negative size"); 370 word size = MutableBytes::allocationSize(length); 371 uword address; 372 CHECK(heap()->allocate(size, &address), "out of memory"); 373 return MutableBytes::cast( 374 DataArray::initialize(address, length, LayoutId::kMutableBytes)); 375} 376 377RawObject Runtime::newBytes(word length, byte fill) { 378 DCHECK(length >= 0, "invalid length %ld", length); 379 if (length <= SmallBytes::kMaxLength) { 380 byte buffer[SmallBytes::kMaxLength]; 381 for (word i = 0; i < SmallBytes::kMaxLength; i++) { 382 buffer[i] = fill; 383 } 384 return SmallBytes::fromBytes({buffer, length}); 385 } 386 HandleScope scope(Thread::current()); 387 LargeBytes result(&scope, createLargeBytes(length)); 388 std::memset(reinterpret_cast<byte*>(result.address()), fill, length); 389 return *result; 390} 391 392RawObject Runtime::newBytesWithAll(View<byte> array) { 393 word length = array.length(); 394 if (length <= SmallBytes::kMaxLength) { 395 return SmallBytes::fromBytes(array); 396 } 397 HandleScope scope(Thread::current()); 398 LargeBytes result(&scope, createLargeBytes(length)); 399 std::memcpy(reinterpret_cast<byte*>(result.address()), array.data(), length); 400 return *result; 401} 402 403RawObject Runtime::newBytesIterator(Thread* thread, const Bytes& bytes) { 404 HandleScope scope(thread); 405 BytesIterator result(&scope, newInstanceWithSize(LayoutId::kBytesIterator, 406 BytesIterator::kSize)); 407 result.setIndex(0); 408 result.setIterable(*bytes); 409 return *result; 410} 411 412RawObject Runtime::newTraceback() { 413 return newInstanceWithSize(LayoutId::kTraceback, Traceback::kSize); 414} 415 416RawObject Runtime::newType() { return newTypeWithMetaclass(LayoutId::kType); } 417 418RawObject Runtime::newTypeWithMetaclass(LayoutId metaclass_id) { 419 Thread* thread = Thread::current(); 420 HandleScope scope(thread); 421 Type result(&scope, newInstanceWithSize(metaclass_id, Type::kSize)); 422 attributeDictInit(thread, result); 423 result.setFlagsAndBuiltinBase(Type::Flag::kNone, LayoutId::kObject); 424 result.setDoc(NoneType::object()); 425 result.setAbstractMethods(Unbound::object()); 426 return *result; 427} 428 429RawObject Runtime::newTypeProxy(const Type& type) { 430 Thread* thread = Thread::current(); 431 HandleScope scope(thread); 432 TypeProxy result(&scope, 433 newInstanceWithSize(LayoutId::kTypeProxy, TypeProxy::kSize)); 434 result.setType(*type); 435 return *result; 436} 437 438bool Runtime::isCallable(Thread* thread, const Object& obj) { 439 HandleScope scope(thread); 440 if (obj.isFunction() || obj.isBoundMethod() || obj.isType()) { 441 return true; 442 } 443 Type type(&scope, typeOf(*obj)); 444 return !typeLookupInMroById(thread, *type, ID(__call__)).isError(); 445} 446 447bool Runtime::isDeleteDescriptor(Thread* thread, const Object& object) { 448 HandleScope scope(thread); 449 Type type(&scope, typeOf(*object)); 450 return type.hasFlag(Type::Flag::kHasDunderDelete); 451} 452 453bool Runtime::isIterator(Thread* thread, const Object& obj) { 454 HandleScope scope(thread); 455 Type type(&scope, typeOf(*obj)); 456 return !typeLookupInMroById(thread, *type, ID(__next__)).isError(); 457} 458 459bool Runtime::isMapping(Thread* thread, const Object& obj) { 460 if (obj.isDict()) return true; 461 HandleScope scope(thread); 462 Type type(&scope, typeOf(*obj)); 463 return !typeLookupInMroById(thread, *type, ID(__getitem__)).isError(); 464} 465 466bool Runtime::isSequence(Thread* thread, const Object& obj) { 467 if (isInstanceOfDict(*obj)) { 468 return false; 469 } 470 HandleScope scope(thread); 471 Type type(&scope, typeOf(*obj)); 472 return !typeLookupInMroById(thread, *type, ID(__getitem__)).isError(); 473} 474 475RawObject Runtime::newCode(word argcount, word posonlyargcount, 476 word kwonlyargcount, word nlocals, word stacksize, 477 word flags, const Object& code, const Object& consts, 478 const Object& names, const Object& varnames, 479 const Object& freevars, const Object& cellvars, 480 const Object& filename, const Object& name, 481 word firstlineno, const Object& lnotab) { 482 DCHECK(code.isInt() || isInstanceOfBytes(*code), "code must be bytes or int"); 483 DCHECK(isInstanceOfTuple(*consts), "expected tuple"); 484 DCHECK(isInstanceOfTuple(*names), "expected tuple"); 485 DCHECK(isInstanceOfTuple(*varnames), "expected tuple"); 486 DCHECK(isInstanceOfTuple(*freevars), "expected tuple"); 487 DCHECK(isInstanceOfTuple(*cellvars), "expected tuple"); 488 DCHECK(isInstanceOfStr(*filename), "expected str"); 489 DCHECK(isInstanceOfStr(*name), "expected str"); 490 DCHECK(isInstanceOfBytes(*lnotab), "expected bytes"); 491 DCHECK(argcount >= 0, "argcount must not be negative"); 492 DCHECK(posonlyargcount >= 0, "posonlyargcount must not be negative"); 493 DCHECK(kwonlyargcount >= 0, "kwonlyargcount must not be negative"); 494 DCHECK(nlocals >= 0, "nlocals must not be negative"); 495 496 Thread* thread = Thread::current(); 497 HandleScope scope(thread); 498 499 Tuple cellvars_tuple(&scope, tupleUnderlying(*cellvars)); 500 Tuple freevars_tuple(&scope, tupleUnderlying(*freevars)); 501 if (cellvars_tuple.length() == 0 && freevars_tuple.length() == 0) { 502 flags |= Code::Flags::kNofree; 503 } else { 504 flags &= ~Code::Flags::kNofree; 505 } 506 507 if (!code.isInt()) { 508 Bytes code_bytes(&scope, bytesUnderlying(*code)); 509 CHECK(code_bytes.length() <= kMaxUint32, "code objects must fit in 4GB"); 510 } 511 512 Code result(&scope, newInstanceWithSize(LayoutId::kCode, Code::kSize)); 513 result.setArgcount(argcount); 514 result.setPosonlyargcount(posonlyargcount); 515 result.setKwonlyargcount(kwonlyargcount); 516 result.setNlocals(nlocals); 517 result.setStacksize(stacksize); 518 result.setFlags(flags); 519 result.setCode(*code); 520 result.setConsts(*consts); 521 result.setNames(*names); 522 result.setVarnames(*varnames); 523 result.setFreevars(*freevars); 524 result.setCellvars(*cellvars); 525 result.setFilename(*filename); 526 result.setName(*name); 527 result.setFirstlineno(firstlineno); 528 result.setLnotab(*lnotab); 529 result.setIntrinsic(nullptr); 530 531 Tuple varnames_tuple(&scope, tupleUnderlying(*varnames)); 532 if (argcount > varnames_tuple.length() || 533 kwonlyargcount > varnames_tuple.length() || 534 result.totalArgs() > varnames_tuple.length()) { 535 return thread->raiseWithFmt(LayoutId::kValueError, 536 "code: varnames is too small"); 537 } 538 539 strInternInTuple(thread, names); 540 strInternInTuple(thread, varnames); 541 strInternInTuple(thread, freevars); 542 strInternInTuple(thread, cellvars); 543 strInternConstants(thread, consts); 544 545 // Create mapping between cells and arguments if needed 546 if (result.numCellvars() > 0) { 547 MutableTuple cell2arg(&scope, newMutableTuple(result.numCellvars())); 548 cell2arg.fill(NoneType::object()); 549 bool value_set = false; 550 for (word i = 0; i < result.numCellvars(); i++) { 551 for (word j = 0; j < result.totalArgs(); j++) { 552 if (Tuple::cast(*cellvars).at(i) == Tuple::cast(*varnames).at(j)) { 553 cell2arg.atPut(i, newInt(j)); 554 value_set = true; 555 } 556 } 557 } 558 if (value_set) result.setCell2arg(cell2arg.becomeImmutable()); 559 } 560 561 DCHECK(result.totalArgs() <= result.nlocals(), "invalid nlocals count"); 562 return *result; 563} 564 565RawObject Runtime::newBuiltinCode(word argcount, word posonlyargcount, 566 word kwonlyargcount, word flags, 567 BuiltinFunction function, 568 const Object& parameter_names, 569 const Object& name_str) { 570 void* function_ptr = bit_cast<void*>(function); 571 DCHECK((reinterpret_cast<uword>(function_ptr) & 572 (1 << Object::kSmallIntTagBits)) == 0, 573 "function must be aligned"); 574 Thread* thread = Thread::current(); 575 HandleScope scope(thread); 576 Tuple empty_tuple(&scope, emptyTuple()); 577 Object empty_string(&scope, Str::empty()); 578 Object lnotab(&scope, Bytes::empty()); 579 word nlocals = argcount + kwonlyargcount + 580 ((flags & Code::Flags::kVarargs) != 0) + 581 ((flags & Code::Flags::kVarkeyargs) != 0); 582 flags |= Code::Flags::kOptimized | Code::Flags::kNewlocals; 583 Object function_int(&scope, SmallInt::fromAlignedCPtr(function_ptr)); 584 return newCode(argcount, posonlyargcount, kwonlyargcount, nlocals, 585 /*stacksize=*/0, flags, /*code=*/function_int, 586 /*consts=*/empty_tuple, /*names=*/empty_tuple, 587 /*varnames=*/parameter_names, /*freevars=*/empty_tuple, 588 /*cellvars=*/empty_tuple, /*filename=*/empty_string, name_str, 589 /*firstlineno=*/0, lnotab); 590} 591 592RawObject Runtime::newFunction(Thread* thread, const Object& name, 593 const Object& code, word flags, word argcount, 594 word total_args, word total_vars, 595 const Object& stacksize_or_builtin, 596 Function::Entry entry, Function::Entry entry_kw, 597 Function::Entry entry_ex) { 598 DCHECK(isInstanceOfStr(*name), "expected str"); 599 600 HandleScope scope(thread); 601 Function function(&scope, 602 newInstanceWithSize(LayoutId::kFunction, Function::kSize)); 603 function.setCode(*code); 604 function.setFlags(flags); 605 function.setArgcount(argcount); 606 function.setTotalArgs(total_args); 607 function.setTotalVars(total_vars); 608 function.setStacksizeOrBuiltin(*stacksize_or_builtin); 609 function.setName(*name); 610 function.setQualname(*name); 611 function.setEntry(entry); 612 function.setEntryKw(entry_kw); 613 function.setEntryEx(entry_ex); 614 function.setIntrinsic(nullptr); 615 populateEntryAsm(function); 616 return *function; 617} 618 619RawObject Runtime::newFunctionWithCode(Thread* thread, const Object& qualname, 620 const Code& code, 621 const Object& module_obj) { 622 DCHECK(module_obj.isNoneType() || 623 thread->runtime()->isInstanceOfModule(*module_obj), 624 "module_obj should be either None or a Module"); 625 HandleScope scope(thread); 626 627 Function::Entry entry; 628 Function::Entry entry_kw; 629 Function::Entry entry_ex; 630 word flags = code.flags(); 631 if (code.kwonlyargcount() == 0 && (flags & Code::Flags::kNofree) && 632 !(flags & (Code::Flags::kVarargs | Code::Flags::kVarkeyargs))) { 633 flags |= Function::Flags::kSimpleCall; 634 } 635 word stacksize = code.stacksize(); 636 Object stacksize_or_builtin(&scope, NoneType::object()); 637 if (!code.hasOptimizedAndNewlocals()) { 638 // We do not support calling non-optimized functions directly. We only allow 639 // them in Thread::exec() and Thread::runClassFunction(). 640 entry = unimplementedTrampoline; 641 entry_kw = unimplementedTrampoline; 642 entry_ex = unimplementedTrampoline; 643 stacksize_or_builtin = SmallInt::fromWord(stacksize); 644 } else if (code.isNative()) { 645 entry = builtinTrampoline; 646 entry_kw = builtinTrampolineKw; 647 entry_ex = builtinTrampolineEx; 648 stacksize_or_builtin = code.code(); 649 DCHECK(stacksize == 0, "expected zero stacksize"); 650 } else if (code.isGeneratorLike()) { 651 entry = generatorTrampoline; 652 entry_kw = generatorTrampolineKw; 653 entry_ex = generatorTrampolineEx; 654 // HACK: Reserve one extra stack slot for the case where we need to unwrap a 655 // bound method. 656 stacksize++; 657 stacksize_or_builtin = SmallInt::fromWord(stacksize); 658 } else { 659 entry = interpreterTrampoline; 660 entry_kw = interpreterTrampolineKw; 661 entry_ex = interpreterTrampolineEx; 662 flags |= Function::Flags::kInterpreted; 663 // HACK: Reserve one extra stack slot for the case where we need to unwrap a 664 // bound method. 665 stacksize++; 666 stacksize_or_builtin = SmallInt::fromWord(stacksize); 667 } 668 Object name(&scope, code.name()); 669 word total_args = code.totalArgs(); 670 word total_vars = 671 code.nlocals() - total_args + code.numCellvars() + code.numFreevars(); 672 673 Function function( 674 &scope, 675 newFunction(thread, name, code, flags, code.argcount(), total_args, 676 total_vars, stacksize_or_builtin, entry, entry_kw, entry_ex)); 677 function.setIntrinsic(code.intrinsic()); 678 populateEntryAsm(function); 679 680 if (isInstanceOfStr(*qualname)) { 681 function.setQualname(*qualname); 682 } else { 683 DCHECK(qualname.isNoneType(), "expected str or none type"); 684 } 685 686 if (!module_obj.isNoneType()) { 687 Module module(&scope, *module_obj); 688 function.setModuleObject(*module_obj); 689 Object module_name(&scope, moduleAtById(thread, module, ID(__name__))); 690 if (!module_name.isErrorNotFound() && isInstanceOfStr(*module_name)) { 691 function.setModuleName(*module_name); 692 } 693 } else { 694 DCHECK(code.isNative(), "Only native code may have no globals"); 695 } 696 697 Object consts_obj(&scope, code.consts()); 698 if (consts_obj.isTuple()) { 699 Tuple consts(&scope, *consts_obj); 700 if (consts.length() >= 1 && consts.at(0).isStr()) { 701 function.setDoc(consts.at(0)); 702 } 703 } 704 705 if (!code.isNative()) { 706 Bytes bytecode(&scope, code.code()); 707 function.setRewrittenBytecode(expandBytecode(thread, bytecode)); 708 // TODO(T45382423): Move this into a separate function to be called by a 709 // relevant opcode during opcode execution. 710 rewriteBytecode(thread, function); 711 } 712 return *function; 713} 714 715RawObject Runtime::newExceptionState() { 716 return newInstanceWithSize(LayoutId::kExceptionState, ExceptionState::kSize); 717} 718 719RawObject Runtime::newCoroutine() { 720 return newInstanceWithSize(LayoutId::kCoroutine, Coroutine::kSize); 721} 722 723RawObject Runtime::newFrameProxy(Thread* thread, const Object& function, 724 const Object& lasti) { 725 HandleScope scope(thread); 726 FrameProxy result( 727 &scope, newInstanceWithSize(LayoutId::kFrameProxy, FrameProxy::kSize)); 728 result.setFunction(*function); 729 result.setLasti(*lasti); 730 return *result; 731} 732 733RawObject Runtime::newGenerator() { 734 return newInstanceWithSize(LayoutId::kGenerator, Generator::kSize); 735} 736 737RawObject Runtime::newGeneratorFrame(const Function& function) { 738 DCHECK(function.isGeneratorLike(), "expected a generator-like code object"); 739 740 HandleScope scope(Thread::current()); 741 word num_args = function.totalArgs(); 742 word num_vars = function.totalVars(); 743 word stacksize = SmallInt::cast(function.stacksizeOrBuiltin()).value(); 744 // +1 for the function pointer. 745 word extra_words = num_args + num_vars + stacksize + 1; 746 GeneratorFrame frame( 747 &scope, newInstanceWithSize( 748 LayoutId::kGeneratorFrame, 749 GeneratorFrame::numAttributes(extra_words) * kPointerSize)); 750 frame.setMaxStackSize(stacksize); 751 return *frame; 752} 753 754RawObject Runtime::newInstance(const Layout& layout) { 755 // This takes into account the potential overflow pointer. 756 RawInstance instance = 757 Instance::cast(newInstanceWithSize(layout.id(), layout.instanceSize())); 758 // Set the overflow array 759 if (layout.hasTupleOverflow()) { 760 instance.instanceVariableAtPut(layout.overflowOffset(), empty_tuple_); 761 } 762 return instance; 763} 764 765ALWAYS_INLINE USED RawObject Runtime::newInstanceWithSize(LayoutId layout_id, 766 word object_size) { 767 word num_attributes = object_size / kPointerSize; 768 word allocation_size = Instance::allocationSize(num_attributes); 769 uword address; 770 CHECK(heap()->allocate(allocation_size, &address), "out of memory"); 771 return Instance::initializeWithNone(address, num_attributes, layout_id); 772} 773 774RawObject Runtime::newQualname(Thread* thread, const Type& type, 775 SymbolId name) { 776 HandleScope scope(thread); 777 Str type_name(&scope, type.name()); 778 return newStrFromFmt("%S.%Y", &type_name, name); 779} 780 781RawObject Runtime::newDeque() { 782 HandleScope scope(Thread::current()); 783 Deque deque(&scope, newInstanceWithSize(LayoutId::kDeque, Deque::kSize)); 784 deque.setItems(SmallInt::fromWord(0)); 785 deque.setLeft(0); 786 deque.setNumItems(0); 787 deque.setState(0); 788 return *deque; 789} 790 791RawObject Runtime::newDequeIterator(const Deque& deque, word index) { 792 HandleScope scope(Thread::current()); 793 DequeIterator iter(&scope, newInstanceWithSize(LayoutId::kDequeIterator, 794 DequeIterator::kSize)); 795 iter.setIndex(index); 796 iter.setIterable(*deque); 797 iter.setState(deque.state()); 798 return *iter; 799} 800 801RawObject Runtime::newDequeReverseIterator(const Deque& deque, word index) { 802 HandleScope scope(Thread::current()); 803 DequeReverseIterator iter(&scope, 804 newInstanceWithSize(LayoutId::kDequeReverseIterator, 805 DequeReverseIterator::kSize)); 806 iter.setIndex(index); 807 iter.setIterable(*deque); 808 iter.setState(deque.state()); 809 return *iter; 810} 811 812RawObject Runtime::newList() { 813 HandleScope scope(Thread::current()); 814 List result(&scope, newInstanceWithSize(LayoutId::kList, List::kSize)); 815 result.setNumItems(0); 816 result.setItems(empty_tuple_); 817 return *result; 818} 819 820RawObject Runtime::newListIterator(const Object& list) { 821 HandleScope scope(Thread::current()); 822 ListIterator list_iterator( 823 &scope, 824 newInstanceWithSize(LayoutId::kListIterator, ListIterator::kSize)); 825 list_iterator.setIndex(0); 826 list_iterator.setIterable(*list); 827 return *list_iterator; 828} 829 830RawObject Runtime::newSeqIterator(const Object& sequence) { 831 HandleScope scope(Thread::current()); 832 SeqIterator iter( 833 &scope, newInstanceWithSize(LayoutId::kSeqIterator, SeqIterator::kSize)); 834 iter.setIndex(0); 835 iter.setIterable(*sequence); 836 return *iter; 837} 838 839RawObject Runtime::newModule(const Object& name) { 840 Thread* thread = Thread::current(); 841 HandleScope scope(thread); 842 Module result(&scope, newInstanceWithSize(LayoutId::kModule, Module::kSize)); 843 attributeDictInit(thread, result); 844 result.setDef(newIntFromCPtr(nullptr)); 845 result.setId(reserveModuleId()); 846 Object init_result(&scope, moduleInit(thread, result, name)); 847 if (init_result.isErrorException()) return *init_result; 848 return *result; 849} 850 851RawObject Runtime::newModuleProxy(const Module& module) { 852 Thread* thread = Thread::current(); 853 HandleScope scope(thread); 854 ModuleProxy result( 855 &scope, newInstanceWithSize(LayoutId::kModuleProxy, ModuleProxy::kSize)); 856 result.setModule(*module); 857 return *result; 858} 859 860RawObject Runtime::newSlotDescriptor(const Type& type, const Object& name) { 861 Thread* thread = Thread::current(); 862 HandleScope scope(thread); 863 SlotDescriptor result(&scope, newInstanceWithSize(LayoutId::kSlotDescriptor, 864 SlotDescriptor::kSize)); 865 result.setType(*type); 866 result.setName(*name); 867 return *result; 868} 869 870RawObject Runtime::newMemoryView(Thread* thread, const Object& obj, 871 const Object& buffer, word length, 872 ReadOnly read_only) { 873 HandleScope scope(thread); 874 MemoryView result( 875 &scope, newInstanceWithSize(LayoutId::kMemoryView, MemoryView::kSize)); 876 result.setBuffer(*buffer); 877 result.setObject(*obj); 878 result.setLength(length); 879 result.setFormat(RawSmallStr::fromCodePoint('B')); 880 result.setReadOnly(read_only == ReadOnly::ReadOnly); 881 result.setStart(0); 882 Object length_obj(&scope, SmallInt::fromWord(length)); 883 result.setShape(newTupleWith1(length_obj)); 884 Object one(&scope, SmallInt::fromWord(1)); 885 result.setNdim(*one); 886 result.setStrides(newTupleWith1(one)); 887 return *result; 888} 889 890RawObject Runtime::newMemoryViewFromCPtr(Thread* thread, const Object& obj, 891 void* ptr, word length, 892 ReadOnly read_only) { 893 HandleScope scope(thread); 894 Object pointer(&scope, newPointer(ptr, length)); 895 return newMemoryView(thread, obj, pointer, length, read_only); 896} 897 898RawObject Runtime::newMmap() { 899 HandleScope scope(Thread::current()); 900 Mmap result(&scope, newInstanceWithSize(LayoutId::kMmap, Mmap::kSize)); 901 result.setAccess(0); 902 result.setData(NoneType::object()); 903 result.setFd(NoneType::object()); 904 return *result; 905} 906 907RawObject Runtime::newMutableBytesZeroed(word size) { 908 if (size == 0) { 909 return empty_mutable_bytes_; 910 } 911 return createMutableBytes(size); 912} 913 914RawObject Runtime::mutableBytesFromBytes(Thread* thread, const Bytes& bytes) { 915 HandleScope scope(thread); 916 word len = bytes.length(); 917 MutableBytes mb(&scope, createMutableBytes(len)); 918 bytes.copyTo(reinterpret_cast<byte*>(mb.address()), len); 919 return *mb; 920} 921 922RawObject Runtime::mutableBytesWith(word length, byte value) { 923 if (length == 0) return empty_mutable_bytes_; 924 DCHECK(length > 0, "invalid length %ld", length); 925 HandleScope scope(Thread::current()); 926 MutableBytes result(&scope, createMutableBytes(length)); 927 std::memset(reinterpret_cast<byte*>(result.address()), value, length); 928 return *result; 929} 930 931RawObject Runtime::newIntFromCPtr(void* ptr) { 932 return newInt(reinterpret_cast<word>(ptr)); 933} 934 935RawObject Runtime::newMutableTuple(word length) { 936 DCHECK(length > 0, "use emptyTuple() for MutableTuple with length 0"); 937 word size = MutableTuple::allocationSize(length); 938 uword address; 939 CHECK(heap()->allocate(size, &address), "out of memory"); 940 return MutableTuple::cast(MutableTuple::initialize(address, length)); 941} 942 943RawObject Runtime::newTupleWith1(const Object& item1) { 944 RawMutableTuple result = MutableTuple::cast(newMutableTuple(1)); 945 result.atPut(0, *item1); 946 return result.becomeImmutable(); 947} 948 949RawObject Runtime::newTupleWith2(const Object& item1, const Object& item2) { 950 RawMutableTuple result = MutableTuple::cast(newMutableTuple(2)); 951 result.atPut(0, *item1); 952 result.atPut(1, *item2); 953 return result.becomeImmutable(); 954} 955 956RawObject Runtime::newTupleWith3(const Object& item1, const Object& item2, 957 const Object& item3) { 958 RawMutableTuple result = MutableTuple::cast(newMutableTuple(3)); 959 result.atPut(0, *item1); 960 result.atPut(1, *item2); 961 result.atPut(2, *item3); 962 return result.becomeImmutable(); 963} 964 965RawObject Runtime::newTupleWith4(const Object& item1, const Object& item2, 966 const Object& item3, const Object& item4) { 967 RawMutableTuple result = MutableTuple::cast(newMutableTuple(4)); 968 result.atPut(0, *item1); 969 result.atPut(1, *item2); 970 result.atPut(2, *item3); 971 result.atPut(3, *item4); 972 return result.becomeImmutable(); 973} 974 975RawObject Runtime::newTupleWithN(word num_items, const Object* item1, ...) { 976 RawMutableTuple result = MutableTuple::cast(newMutableTuple(num_items)); 977 result.atPut(0, **item1); 978 979 va_list args; 980 va_start(args, item1); 981 for (word i = 1; i < num_items; i++) { 982 const Object* item = va_arg(args, const Object*); 983 result.atPut(i, **item); 984 } 985 va_end(args); 986 987 return result.becomeImmutable(); 988} 989 990NEVER_INLINE 991RawObject Runtime::newLargeIntFromWord(word value) { 992 DCHECK(!SmallInt::isValid(value), "value must not fit into SmallInt"); 993 uword digit[1] = {static_cast<uword>(value)}; 994 return newLargeIntWithDigits(digit); 995} 996 997RawObject Runtime::newIntFromUnsigned(uword value) { 998 if (static_cast<word>(value) >= 0 && SmallInt::isValid(value)) { 999 return SmallInt::fromWord(value); 1000 } 1001 uword digits[] = {value, 0}; 1002 View<uword> view(digits, digits[0] >> (kBitsPerWord - 1) ? 2 : 1); 1003 return newLargeIntWithDigits(view); 1004} 1005 1006RawObject Runtime::newFloat(double value) { 1007 uword address; 1008 CHECK(heap()->allocate(Float::allocationSize(), &address), "out of memory"); 1009 return Float::cast(Float::initialize(address, value)); 1010} 1011 1012RawObject Runtime::newComplex(double real, double imag) { 1013 uword address; 1014 CHECK(heap()->allocate(Complex::allocationSize(), &address), "out of memory"); 1015 return Complex::cast(Complex::initialize(address, real, imag)); 1016} 1017 1018RawObject Runtime::newLargeIntWithDigits(View<uword> digits) { 1019 word length = digits.length(); 1020 DCHECK(length > 0, "must have at least 1 digit"); 1021 DCHECK(length > 1 || !SmallInt::isValid(digits.get(0)), 1022 "must not fit into a SmallInt"); 1023 HandleScope scope(Thread::current()); 1024 LargeInt result(&scope, createLargeInt(digits.length())); 1025 for (word i = 0; i < digits.length(); i++) { 1026 result.digitAtPut(i, digits.get(i)); 1027 } 1028 DCHECK(result.isValid(), "Invalid digits"); 1029 return *result; 1030} 1031 1032RawObject Runtime::newPointer(void* cptr, word length) { 1033 uword address; 1034 CHECK(heap()->allocate(Pointer::allocationSize(), &address), "out of memory"); 1035 return Pointer::cast(Pointer::initialize(address, cptr, length)); 1036} 1037 1038RawObject Runtime::newProperty(const Object& getter, const Object& setter, 1039 const Object& deleter) { 1040 HandleScope scope(Thread::current()); 1041 Property new_prop(&scope, 1042 newInstanceWithSize(LayoutId::kProperty, Property::kSize)); 1043 new_prop.setGetter(*getter); 1044 new_prop.setSetter(*setter); 1045 new_prop.setDeleter(*deleter); 1046 return *new_prop; 1047} 1048 1049RawObject Runtime::newRange(const Object& start, const Object& stop, 1050 const Object& step) { 1051 HandleScope scope(Thread::current()); 1052 Range result(&scope, newInstanceWithSize(LayoutId::kRange, Range::kSize)); 1053 result.setStart(*start); 1054 result.setStop(*stop); 1055 result.setStep(*step); 1056 return *result; 1057} 1058 1059RawObject Runtime::newLongRangeIterator(const Int& start, const Int& stop, 1060 const Int& step) { 1061 HandleScope scope(Thread::current()); 1062 LongRangeIterator result(&scope, 1063 newInstanceWithSize(LayoutId::kLongRangeIterator, 1064 LongRangeIterator::kSize)); 1065 result.setNext(*start); 1066 result.setStop(*stop); 1067 result.setStep(*step); 1068 return *result; 1069} 1070 1071RawObject Runtime::newRangeIterator(word start, word step, word length) { 1072 HandleScope scope(Thread::current()); 1073 RangeIterator result(&scope, newInstanceWithSize(LayoutId::kRangeIterator, 1074 RangeIterator::kSize)); 1075 result.setNext(start); 1076 result.setStep(step); 1077 result.setLength(length); 1078 return *result; 1079} 1080 1081RawObject Runtime::newSetIterator(const Object& set) { 1082 HandleScope scope(Thread::current()); 1083 SetIterator result( 1084 &scope, newInstanceWithSize(LayoutId::kSetIterator, SetIterator::kSize)); 1085 result.setIterable(*set); 1086 result.setIndex(0); 1087 result.setConsumedCount(0); 1088 return *result; 1089} 1090 1091RawObject Runtime::newSlice(const Object& start, const Object& stop, 1092 const Object& step) { 1093 if (start.isNoneType() && stop.isNoneType() && step.isNoneType()) { 1094 return emptySlice(); 1095 } 1096 HandleScope scope(Thread::current()); 1097 Slice slice(&scope, newInstanceWithSize(LayoutId::kSlice, Slice::kSize)); 1098 slice.setStart(*start); 1099 slice.setStop(*stop); 1100 slice.setStep(*step); 1101 return *slice; 1102} 1103 1104RawObject Runtime::newStaticMethod() { 1105 return newInstanceWithSize(LayoutId::kStaticMethod, StaticMethod::kSize); 1106} 1107 1108RawObject Runtime::newStrArray() { 1109 HandleScope scope(Thread::current()); 1110 StrArray result(&scope, 1111 newInstanceWithSize(LayoutId::kStrArray, StrArray::kSize)); 1112 result.setItems(empty_mutable_bytes_); 1113 result.setNumItems(0); 1114 return *result; 1115} 1116 1117RawObject Runtime::newStrFromCStr(const char* c_str) { 1118 word length = std::strlen(c_str); 1119 auto data = reinterpret_cast<const byte*>(c_str); 1120 return newStrWithAll(View<byte>(data, length)); 1121} 1122 1123RawObject Runtime::strFromStrArray(const StrArray& array) { 1124 word length = array.numItems(); 1125 if (length <= SmallStr::kMaxLength) { 1126 byte buffer[SmallStr::kMaxLength]; 1127 array.copyTo(buffer, length); 1128 return SmallStr::fromBytes({buffer, length}); 1129 } 1130 HandleScope scope(Thread::current()); 1131 LargeStr result(&scope, createLargeStr(length)); 1132 array.copyTo(reinterpret_cast<byte*>(result.address()), length); 1133 return *result; 1134} 1135 1136static word strFormat(Thread* thread, const MutableBytes& dst, 1137 bool determine_size, const char* fmt, va_list args) { 1138 HandleScope scope(thread); 1139 word fragment_begin = 0; 1140 word fmt_index = 0; 1141 word dst_index = 0; 1142 word size = determine_size ? -1 : dst.length(); 1143 for (; fmt[fmt_index] != '\0'; fmt_index++) { 1144 if (fmt[fmt_index] != '%') { 1145 continue; 1146 } 1147 word fragment_length = fmt_index - fragment_begin; 1148 if (!determine_size) { 1149 std::memcpy(reinterpret_cast<void*>(dst.address() + dst_index), 1150 fmt + fragment_begin, fragment_length); 1151 } 1152 dst_index += fragment_length; 1153 fmt_index++; 1154 fragment_begin = fmt_index + 1; 1155 switch (fmt[fmt_index]) { 1156 case 'c': { 1157 int value_int = va_arg(args, int); // Note that C promotes char to int. 1158 if (value_int < 0 || value_int > kMaxASCII) { 1159 // Replace non-ASCII characters. 1160 RawSmallStr value = SmallStr::fromCodePoint(kReplacementCharacter); 1161 word length = value.length(); 1162 if (!determine_size) { 1163 dst.replaceFromWithStr(dst_index, Str::cast(value), length); 1164 } 1165 dst_index += length; 1166 break; 1167 } 1168 if (!determine_size) { 1169 dst.byteAtPut(dst_index, static_cast<char>(value_int)); 1170 } 1171 dst_index++; 1172 } break; 1173 case 'd': { 1174 int value = va_arg(args, int); 1175 char* print_dst = 1176 determine_size ? nullptr 1177 : reinterpret_cast<char*>(dst.address() + dst_index); 1178 size_t print_len = determine_size ? 0 : size - dst_index + 1; 1179 dst_index += std::snprintf(print_dst, print_len, "%d", value); 1180 } break; 1181 case 'g': { 1182 double value = va_arg(args, double); 1183 char* print_dst = 1184 determine_size ? nullptr 1185 : reinterpret_cast<char*>(dst.address() + dst_index); 1186 size_t print_len = determine_size ? 0 : size - dst_index + 1; 1187 dst_index += std::snprintf(print_dst, print_len, "%g", value); 1188 } break; 1189 case 's': { 1190 const char* value = va_arg(args, char*); 1191 word length = std::strlen(value); 1192 if (!determine_size) { 1193 std::memcpy(reinterpret_cast<byte*>(dst.address() + dst_index), value, 1194 length); 1195 } 1196 dst_index += length; 1197 } break; 1198 case 'w': { 1199 word value = va_arg(args, word); 1200 char* print_dst = 1201 determine_size ? nullptr 1202 : reinterpret_cast<char*>(dst.address() + dst_index); 1203 size_t print_len = determine_size ? 0 : size - dst_index + 1; 1204 dst_index += std::snprintf(print_dst, print_len, "%" PRIdPTR, value); 1205 } break; 1206 case 'x': { 1207 unsigned value = va_arg(args, unsigned); 1208 char* print_dst = 1209 determine_size ? nullptr 1210 : reinterpret_cast<char*>(dst.address() + dst_index); 1211 size_t print_len = determine_size ? 0 : size - dst_index + 1; 1212 dst_index += std::snprintf(print_dst, print_len, "%x", value); 1213 } break; 1214 case 'C': { 1215 int32_t value_int = va_arg(args, int32_t); 1216 if (value_int < 0 || value_int > kMaxUnicode) { 1217 value_int = kReplacementCharacter; 1218 } 1219 RawSmallStr value = SmallStr::fromCodePoint(value_int); 1220 word length = value.length(); 1221 if (!determine_size) { 1222 dst.replaceFromWithStr(dst_index, Str::cast(value), length); 1223 } 1224 dst_index += length; 1225 } break; 1226 case 'S': { 1227 Object value_obj(&scope, **va_arg(args, Object*)); 1228 Str value(&scope, strUnderlying(*value_obj)); 1229 word length = value.length(); 1230 if (!determine_size) { 1231 dst.replaceFromWithStr(dst_index, *value, length); 1232 } 1233 dst_index += length; 1234 } break; 1235 case 'F': { 1236 Object obj(&scope, **va_arg(args, Object*)); 1237 Function function(&scope, *obj); 1238 Str value(&scope, function.qualname()); 1239 word length = value.length(); 1240 if (!determine_size) { 1241 dst.replaceFromWithStr(dst_index, *value, length); 1242 } 1243 dst_index += length; 1244 } break; 1245 case 'T': { 1246 Object obj(&scope, **va_arg(args, Object*)); 1247 Type type(&scope, thread->runtime()->typeOf(*obj)); 1248 Str value(&scope, type.name()); 1249 word length = value.length(); 1250 if (!determine_size) { 1251 dst.replaceFromWithStr(dst_index, *value, length); 1252 } 1253 dst_index += length; 1254 } break; 1255 case 'Y': { 1256 SymbolId symbol = va_arg(args, SymbolId); 1257 RawStr value = Str::cast(thread->runtime()->symbols()->at(symbol)); 1258 word length = value.length(); 1259 if (!determine_size) { 1260 dst.replaceFromWithStr(dst_index, value, length); 1261 } 1262 dst_index += length; 1263 } break; 1264 case '%': 1265 if (!determine_size) { 1266 dst.byteAtPut(dst_index, '%'); 1267 } 1268 dst_index++; 1269 break; 1270 default: 1271 UNIMPLEMENTED("Unsupported format specifier"); 1272 } 1273 DCHECK(determine_size || dst_index <= size, "dst buffer overflow"); 1274 } 1275 1276 word fragment_length = fmt_index - fragment_begin; 1277 if (!determine_size) { 1278 std::memcpy(reinterpret_cast<void*>(dst.address() + dst_index), 1279 fmt + fragment_begin, fragment_length); 1280 } 1281 dst_index += fragment_length; 1282 DCHECK(determine_size || dst_index == size, "dst buffer underflow"); 1283 return dst_index; 1284} 1285 1286RawObject Runtime::newStrFromFmtV(Thread* thread, const char* fmt, 1287 va_list args) { 1288 va_list args_copy; 1289 va_copy(args_copy, args); 1290 HandleScope scope(thread); 1291 MutableBytes result(&scope, emptyMutableBytes()); 1292 word length = strFormat(thread, result, /*determine_size=*/true, fmt, args); 1293 result = newMutableBytesUninitialized(length); 1294 strFormat(thread, result, /*determine_size=*/false, fmt, args_copy); 1295 va_end(args_copy); 1296 return result.becomeStr(); 1297} 1298 1299RawObject Runtime::newStrFromFmt(const char* fmt, ...) { 1300 va_list args; 1301 va_start(args, fmt); 1302 Thread* thread = Thread::current(); 1303 HandleScope scope(thread); 1304 Object result(&scope, newStrFromFmtV(thread, fmt, args)); 1305 va_end(args); 1306 return *result; 1307} 1308 1309RawObject Runtime::newStrFromUTF32(View<int32_t> code_units) { 1310 word size = 0; 1311 for (word i = 0; i < code_units.length(); ++i) { 1312 int32_t cp = code_units.get(i); 1313 if (cp <= kMaxASCII) { 1314 size += 1; 1315 } else if (cp < 0x0800) { 1316 size += 2; 1317 } else if (cp < 0x010000) { 1318 size += 3; 1319 } else { 1320 DCHECK(cp <= kMaxUnicode, "invalid codepoint"); 1321 size += 4; 1322 } 1323 } 1324 if (size <= RawSmallStr::kMaxLength) { 1325 byte dst[SmallStr::kMaxLength]; 1326 for (word i = 0, j = 0; i < code_units.length(); ++i) { 1327 RawSmallStr src = SmallStr::fromCodePoint(code_units.get(i)); 1328 word num_bytes = src.length(); 1329 src.copyTo(&dst[j], num_bytes); 1330 j += num_bytes; 1331 } 1332 return SmallStr::fromBytes(View<byte>(dst, size)); 1333 } 1334 RawObject result = createLargeStr(size); 1335 DCHECK(!result.isError(), "failed to create large string"); 1336 byte* dst = reinterpret_cast<byte*>(LargeStr::cast(result).address()); 1337 if (code_units.length() == size) { 1338 // ASCII fastpath 1339 for (word i = 0; i < size; ++i) { 1340 dst[i] = code_units.get(i); 1341 } 1342 return result; 1343 } 1344 for (word i = 0, j = 0; i < code_units.length(); ++i) { 1345 RawSmallStr src = SmallStr::fromCodePoint(code_units.get(i)); 1346 word num_bytes = src.length(); 1347 src.copyTo(&dst[j], num_bytes); 1348 j += num_bytes; 1349 } 1350 return result; 1351} 1352 1353RawObject Runtime::newStrWithAll(View<byte> code_units) { 1354 word length = code_units.length(); 1355 if (length <= RawSmallStr::kMaxLength) { 1356 return SmallStr::fromBytes(code_units); 1357 } 1358 RawObject result = createLargeStr(length); 1359 DCHECK(!result.isError(), "failed to create large string"); 1360 byte* dst = reinterpret_cast<byte*>(LargeStr::cast(result).address()); 1361 const byte* src = code_units.data(); 1362 memcpy(dst, src, length); 1363 return result; 1364} 1365 1366void NEVER_INLINE Runtime::internSetGrow(Thread* thread) { 1367 interned_ = py::internSetGrow(thread, MutableTuple::cast(interned_), 1368 &interned_remaining_); 1369} 1370 1371RawObject Runtime::internLargeStr(Thread* thread, const Object& str) { 1372 Runtime* runtime = thread->runtime(); 1373 RawObject result = NoneType::object(); 1374 if (internSetAdd(thread, MutableTuple::cast(runtime->interned_), str, 1375 &result)) { 1376 DCHECK(result == str, "expected str"); 1377 if (--runtime->interned_remaining_ == 0) { 1378 runtime->internSetGrow(thread); 1379 return *str; 1380 } 1381 } 1382 return result; 1383} 1384 1385RawObject Runtime::internStrFromAll(Thread* thread, View<byte> bytes) { 1386 if (bytes.length() <= SmallStr::kMaxLength) { 1387 return SmallStr::fromBytes(bytes); 1388 } 1389 1390 Runtime* runtime = thread->runtime(); 1391 RawObject result = NoneType::object(); 1392 if (internSetAddFromAll(thread, MutableTuple::cast(runtime->interned_), bytes, 1393 &result)) { 1394 if (--runtime->interned_remaining_ == 0) { 1395 HandleScope scope(thread); 1396 Object result_obj(&scope, result); 1397 runtime->internSetGrow(thread); 1398 return *result_obj; 1399 } 1400 } 1401 return result; 1402} 1403 1404RawObject Runtime::internStrFromCStr(Thread* thread, const char* c_str) { 1405 View<byte> bytes(reinterpret_cast<const byte*>(c_str), std::strlen(c_str)); 1406 return internStrFromAll(thread, bytes); 1407} 1408 1409bool Runtime::isInternedStr(Thread* thread, const Object& str) { 1410 DCHECK(str.isStr(), "expected str"); 1411 if (str.isSmallStr()) { 1412 return true; 1413 } 1414 return internSetContains(MutableTuple::cast(thread->runtime()->interned_), 1415 LargeStr::cast(*str)); 1416} 1417 1418word Runtime::hash(RawObject object) { 1419 if (!object.isHeapObject()) { 1420 return immediateHash(object); 1421 } 1422 if (object.isLargeBytes() || object.isLargeStr()) { 1423 return valueHash(object); 1424 } 1425 return identityHash(object); 1426} 1427 1428word Runtime::immediateHash(RawObject object) { 1429 if (object.isSmallStr()) { 1430 return SmallStr::cast(object).hash(); 1431 } 1432 if (object.isSmallInt()) { 1433 return SmallInt::cast(object).hash(); 1434 } 1435 if (object.isBool()) { 1436 return Bool::cast(object).hash(); 1437 } 1438 if (object.isSmallBytes()) { 1439 return SmallBytes::cast(object).hash(); 1440 } 1441 return static_cast<word>(object.raw()); 1442} 1443 1444// Xoroshiro128+ 1445// http://xoroshiro.di.unimi.it/ 1446uword Runtime::random() { 1447 const uint64_t s0 = random_state_.state[0]; 1448 uint64_t s1 = random_state_.state[1]; 1449 const uint64_t result = s0 + s1; 1450 s1 ^= s0; 1451 random_state_.state[0] = Utils::rotateLeft(s0, 55) ^ s1 ^ (s1 << 14); 1452 random_state_.state[1] = Utils::rotateLeft(s1, 36); 1453 return result; 1454} 1455 1456RawObject* Runtime::finalizableReferences() { return &finalizable_references_; } 1457 1458word Runtime::identityHash(RawObject object) { 1459 RawHeapObject src = HeapObject::cast(object); 1460 word code = src.header().hashCode(); 1461 if (code == RawHeader::kUninitializedHash) { 1462 code = random() & RawHeader::kHashCodeMask; 1463 code = (code == RawHeader::kUninitializedHash) ? code + 1 : code; 1464 src.setHeader(src.header().withHashCode(code)); 1465 } 1466 return code; 1467} 1468 1469word Runtime::siphash24(View<byte> array) { 1470 word result = 0; 1471 ::halfsiphash( 1472 array.data(), array.length(), 1473 reinterpret_cast<const uint8_t*>(&random_state_.siphash24_secret), 1474 reinterpret_cast<uint8_t*>(&result), sizeof(result)); 1475 return result; 1476} 1477 1478uint64_t Runtime::hashWithKey(const Bytes& bytes, uint64_t key) { 1479 uint64_t result = 0; 1480 word length = bytes.length(); 1481 byte small_buffer[SmallBytes::kMaxLength]; 1482 byte* data; 1483 if (bytes.isSmallBytes()) { 1484 bytes.copyTo(small_buffer, length); 1485 data = small_buffer; 1486 } else { 1487 data = reinterpret_cast<byte*>(LargeBytes::cast(*bytes).address()); 1488 } 1489 ::halfsiphash(data, length, reinterpret_cast<const uint8_t*>(&key), 1490 reinterpret_cast<uint8_t*>(&result), sizeof(result)); 1491 return result; 1492} 1493 1494word Runtime::bytesHash(View<byte> array) { 1495 word result = siphash24(array); 1496 result &= RawHeader::kHashCodeMask; 1497 return (result == RawHeader::kUninitializedHash) ? result + 1 : result; 1498} 1499 1500word Runtime::valueHash(RawObject object) { 1501 RawHeapObject src = HeapObject::cast(object); 1502 RawHeader header = src.header(); 1503 word code = header.hashCode(); 1504 if (code == RawHeader::kUninitializedHash) { 1505 word size = src.headerCountOrOverflow(); 1506 code = bytesHash(View<byte>(reinterpret_cast<byte*>(src.address()), size)); 1507 src.setHeader(header.withHashCode(code)); 1508 DCHECK(code == src.header().hashCode(), "hash failure"); 1509 } 1510 return code; 1511} 1512 1513const byte* Runtime::hashSecret(size_t size) { 1514 CHECK(size <= sizeof(random_state_.extra_secret), 1515 "hash secret request too big"); 1516 return reinterpret_cast<const byte*>(&random_state_.extra_secret); 1517} 1518 1519RawObject Runtime::handlePendingSignals(Thread* thread) { 1520 thread->clearInterrupt(Thread::kSignal); 1521 if (!is_signal_pending_ || !thread->isMainThread()) { 1522 return NoneType::object(); 1523 } 1524 1525 is_signal_pending_ = false; 1526 HandleScope scope(thread); 1527 for (word i = 1; i < OS::kNumSignals; i++) { 1528 if (OS::pending_signals_[i]) { 1529 OS::pending_signals_[i] = false; 1530 1531 // NOTE: we do not expose frame objects to the user 1532 Object callback(&scope, signalCallback(i)); 1533 Object signum(&scope, SmallInt::fromWord(i)); 1534 Object frame(&scope, NoneType::object()); 1535 Object result(&scope, 1536 Interpreter::call2(thread, callback, signum, frame)); 1537 1538 if (result.isErrorException()) { 1539 is_signal_pending_ = true; 1540 return *result; 1541 } 1542 } 1543 } 1544 1545 return NoneType::object(); 1546} 1547 1548void Runtime::initializeSignals(Thread* thread, const Module& under_signal) { 1549 if (!signal_callbacks_.isNoneType()) { 1550 return; // already initialized 1551 } 1552 1553 signal_stack_ = std::malloc(SIGSTKSZ); 1554 CHECK(signal_stack_ != nullptr, "out of memory"); 1555 1556 stack_t altstack; 1557 altstack.ss_sp = signal_stack_; 1558 altstack.ss_size = SIGSTKSZ; 1559 altstack.ss_flags = 0; 1560 CHECK(::sigaltstack(&altstack, nullptr) == 0, 1561 "unable to create signal-handling stack"); 1562 1563 HandleScope scope(thread); 1564 MutableTuple callbacks(&scope, newMutableTuple(OS::kNumSignals)); 1565 1566 is_signal_pending_ = false; 1567 signal_callbacks_ = *callbacks; 1568 1569 OS::pending_signals_[0] = false; 1570 for (int i = 1; i < OS::kNumSignals; i++) { 1571 OS::pending_signals_[i] = false; 1572 SignalHandler handler = OS::signalHandler(i); 1573 if (handler == SIG_DFL) { 1574 callbacks.atPut(i, kDefaultHandler); 1575 } else if (handler == SIG_IGN) { 1576 callbacks.atPut(i, kIgnoreHandler); 1577 } 1578 } 1579 1580 if (callbacks.at(SIGINT) == kDefaultHandler) { 1581 callbacks.atPut( 1582 SIGINT, moduleAtById(thread, under_signal, ID(default_int_handler))); 1583 OS::setSignalHandler(SIGINT, handleSignal); 1584 } 1585} 1586 1587void Runtime::finalizeSignals(Thread* thread) { 1588 if (signal_callbacks_.isNoneType()) return; 1589 1590 stack_t altstack = {}; 1591 altstack.ss_size = SIGSTKSZ; 1592 altstack.ss_flags = SS_DISABLE; 1593 CHECK(::sigaltstack(&altstack, nullptr) == 0, 1594 "unable to disable signal-handling stack"); 1595 std::free(signal_stack_); 1596 1597 HandleScope scope(thread); 1598 MutableTuple callbacks(&scope, signal_callbacks_); 1599 Object callback(&scope, NoneType::object()); 1600 for (int i = 1; i < OS::kNumSignals; i++) { 1601 callback = callbacks.at(i); 1602 if (callback != kDefaultHandler && callback != kIgnoreHandler) { 1603 OS::setSignalHandler(i, SIG_DFL); 1604 } 1605 } 1606} 1607 1608void Runtime::setPendingSignal(Thread* thread, int signum) { 1609 if (thread != main_thread_) return; 1610 1611 OS::pending_signals_[signum] = true; 1612 is_signal_pending_ = true; 1613 thread->interrupt(Thread::kSignal); 1614 1615 if (wakeup_fd_ < 0) return; 1616 1617 byte b = signum; 1618 File::write(wakeup_fd_, &b, 1); 1619 // TODO(wmeehan): add pending call to report wakeup error 1620} 1621 1622RawObject Runtime::setSignalCallback(word signum, const Object& callback) { 1623 RawMutableTuple callbacks = MutableTuple::cast(signal_callbacks_); 1624 RawObject result = callbacks.at(signum); 1625 callbacks.atPut(signum, *callback); 1626 return result; 1627} 1628 1629RawObject Runtime::signalCallback(word signum) { 1630 return Tuple::cast(signal_callbacks_).at(signum); 1631} 1632 1633void Runtime::populateEntryAsm(const Function& function) { 1634 function.setEntryAsm(interpreter_->entryAsm(function)); 1635} 1636 1637static const word kFixedSpaceSize = 1 * kGiB; 1638 1639void Runtime::initializeJITState() { 1640 machine_code_ = new Space(kFixedSpaceSize); 1641 // TODO(T89276586): Only set X bit per-page after code is written and 1642 // finalized. 1643 OS::protectMemory(reinterpret_cast<byte*>(machine_code_->start()), 1644 machine_code_->size(), OS::kReadWriteExecute); 1645} 1646 1647void Runtime::initializeLayouts() { 1648 layouts_ = newMutableTuple(kInitialLayoutTupleCapacity); 1649 static_assert( 1650 static_cast<word>(LayoutId::kLastBuiltinId) < kInitialLayoutTupleCapacity, 1651 "initial layout tuple size too small"); 1652 num_layouts_ = static_cast<word>(LayoutId::kLastBuiltinId) + 1; 1653 layout_type_transitions_ = 1654 newMutableTuple(LayoutTypeTransition::kTransitionSize); 1655} 1656 1657static const BuiltinAttribute kExceptionStateAttributes[] = { 1658 {ID(_exception_state__type), ExceptionState::kTypeOffset, 1659 AttributeFlags::kHidden}, 1660 {ID(_exception_state__value), ExceptionState::kValueOffset, 1661 AttributeFlags::kHidden}, 1662 {ID(_exception_state__traceback), ExceptionState::kTracebackOffset, 1663 AttributeFlags::kHidden}, 1664 {ID(_exception_state__previous), ExceptionState::kPreviousOffset, 1665 AttributeFlags::kHidden}, 1666}; 1667 1668static const BuiltinAttribute kPointerAttributes[] = { 1669 {ID(_pointer__cptr), Pointer::kCPtrOffset, AttributeFlags::kHidden}, 1670 {ID(_pointer__length), Pointer::kLengthOffset, AttributeFlags::kHidden}, 1671}; 1672 1673void Runtime::initializeTypes(Thread* thread) { 1674 initializeObjectTypes(thread); 1675 1676 initializeArrayType(thread); 1677 initializeBytearrayTypes(thread); 1678 initializeBytesTypes(thread); 1679 initializeCodeType(thread); 1680 initializeComplexType(thread); 1681 initializeDescriptorTypes(thread); 1682 initializeDictTypes(thread); 1683 initializeExceptionTypes(thread); 1684 initializeFloatType(thread); 1685 initializeFrameProxyType(thread); 1686 initializeFunctionTypes(thread); 1687 initializeGeneratorTypes(thread); 1688 initializeIntTypes(thread); 1689 initializeIteratorType(thread); 1690 initializeLayoutType(thread); 1691 initializeListTypes(thread); 1692 initializeMappingProxyType(thread); 1693 initializeMemoryViewType(thread); 1694 initializeMmapType(thread); 1695 initializeModuleProxyType(thread); 1696 initializeModuleType(thread); 1697 initializeRangeTypes(thread); 1698 initializeRefTypes(thread); 1699 initializeSetTypes(thread); 1700 initializeSliceType(thread); 1701 initializeStrArrayType(thread); 1702 initializeStrTypes(thread); 1703 initializeSuperType(thread); 1704 initializeTracebackType(thread); 1705 initializeTupleTypes(thread); 1706 initializeTypeTypes(thread); 1707 initializeUnderCollectionsTypes(thread); 1708 initializeUnderContextvarsTypes(thread); 1709 initializeUnderIOTypes(thread); 1710 initializeValueCellTypes(thread); 1711 1712 addBuiltinType(thread, ID(ExceptionState), LayoutId::kExceptionState, 1713 LayoutId::kObject, kExceptionStateAttributes, 1714 ExceptionState::kSize, /*basetype=*/false); 1715 addBuiltinType(thread, ID(_mutablebytes), LayoutId::kMutableBytes, 1716 LayoutId::kObject, kNoAttributes, MutableBytes::kSize, 1717 /*basetype=*/false); 1718 addBuiltinType(thread, ID(_mutabletuple), LayoutId::kMutableTuple, 1719 LayoutId::kObject, kNoAttributes, MutableTuple::kSize, 1720 /*basetype=*/false); 1721 addBuiltinType(thread, ID(_pointer), LayoutId::kPointer, LayoutId::kObject, 1722 kPointerAttributes, Pointer::kSize, /*basetype=*/false); 1723 addBuiltinType(thread, ID(ellipsis), LayoutId::kEllipsis, LayoutId::kObject, 1724 kNoAttributes, Ellipsis::kSize, /*basetype=*/false); 1725} 1726 1727void Runtime::collectGarbageInto(CompactionDestination destination) { 1728 EVENT(CollectGarbage); 1729 bool run_callback = callbacks_ == NoneType::object(); 1730 RawObject cb = (destination == CompactionDestination::kImmortalPartition) 1731 ? scavengeImmortalize(this) 1732 : scavenge(this); 1733 callbacks_ = WeakRef::spliceQueue(callbacks_, cb); 1734 if (run_callback) { 1735 processCallbacks(); 1736 } 1737 if (finalizable_references_ != NoneType::object()) { 1738 processFinalizers(); 1739 } 1740} 1741 1742Thread* Runtime::newThread() { 1743 Thread* thread = new Thread(this, Thread::kDefaultStackSize); 1744 { 1745 MutexGuard lock(&threads_mutex_); 1746 if (main_thread_ == nullptr) { 1747 main_thread_ = thread; 1748 } else { 1749 Thread* next = main_thread_->next(); 1750 main_thread_->setNext(thread); 1751 thread->setNext(next); 1752 thread->setPrev(main_thread_); 1753 if (next != nullptr) { 1754 next->setPrev(thread); 1755 } 1756 } 1757 } 1758 return thread; 1759} 1760 1761void Runtime::deleteThread(Thread* thread) { 1762 CHECK(thread != main_thread_, "cannot delete main thread"); 1763 MutexGuard lock(&threads_mutex_); 1764 Thread* prev = thread->prev(); 1765 Thread* next = thread->next(); 1766 prev->setNext(next); 1767 if (next != nullptr) { 1768 next->setPrev(prev); 1769 } 1770 delete thread; 1771} 1772 1773void Runtime::processCallbacks() { 1774 Thread* thread = Thread::current(); 1775 HandleScope scope(thread); 1776 Object saved_type(&scope, thread->pendingExceptionType()); 1777 Object saved_value(&scope, thread->pendingExceptionValue()); 1778 Object saved_traceback(&scope, thread->pendingExceptionTraceback()); 1779 thread->clearPendingException(); 1780 1781 while (callbacks_ != NoneType::object()) { 1782 Object weak(&scope, WeakRef::dequeue(&callbacks_)); 1783 BoundMethod callback(&scope, WeakRef::cast(*weak).callback()); 1784 Interpreter::call0(thread, callback); 1785 thread->ignorePendingException(); 1786 WeakRef::cast(*weak).setCallback(NoneType::object()); 1787 } 1788 1789 thread->setPendingExceptionType(*saved_type); 1790 thread->setPendingExceptionValue(*saved_value); 1791 thread->setPendingExceptionTraceback(*saved_traceback); 1792} 1793 1794void Runtime::processFinalizers() { 1795 Thread* thread = Thread::current(); 1796 HandleScope scope(thread); 1797 Object saved_type(&scope, thread->pendingExceptionType()); 1798 Object saved_value(&scope, thread->pendingExceptionValue()); 1799 Object saved_traceback(&scope, thread->pendingExceptionTraceback()); 1800 thread->clearPendingException(); 1801 1802 while (finalizable_references_ != NoneType::object()) { 1803 finalizeExtensionObject(thread, 1804 RawNativeProxy::dequeue(&finalizable_references_)); 1805 } 1806 1807 thread->setPendingExceptionType(*saved_type); 1808 thread->setPendingExceptionValue(*saved_value); 1809 thread->setPendingExceptionTraceback(*saved_traceback); 1810} 1811 1812static void writeCStr(word fd, const char* str) { 1813 File::write(fd, str, std::strlen(str)); 1814} 1815 1816static void writeStr(word fd, RawStr str) { 1817 static const word buffer_length = 128; 1818 byte buffer[buffer_length]; 1819 1820 word start = 0; 1821 word length = str.length(); 1822 while (length > buffer_length) { 1823 LargeStr::cast(str).copyToStartAt(buffer, buffer_length, start); 1824 File::write(fd, buffer, buffer_length); 1825 start += buffer_length; 1826 length -= buffer_length; 1827 } 1828 str.copyToStartAt(buffer, length, start); 1829 File::write(fd, buffer, length); 1830} 1831 1832RawObject Runtime::printTraceback(Thread* thread, word fd) { 1833 // NOTE: all operations in this function must be async-signal-safe. 1834 // See http://man7.org/linux/man-pages/man7/signal-safety.7.html for details. 1835 static const char* in = " in "; 1836 static const char* line = ", line "; 1837 static const char* unknown = "???"; 1838 writeCStr(fd, "Stack (most recent call first):\n"); 1839 1840 Frame* frame = thread->currentFrame(); 1841 while (!frame->isSentinel()) { 1842 writeCStr(fd, " File "); 1843 RawFunction function = frame->function(); 1844 RawObject code_obj = function.code(); 1845 if (code_obj.isCode()) { 1846 RawCode code = Code::cast(code_obj); 1847 RawObject filename = code.filename(); 1848 if (filename.isStr()) { 1849 writeCStr(fd, "\""); 1850 writeStr(fd, RawStr::cast(filename)); 1851 writeCStr(fd, "\""); 1852 } else { 1853 writeCStr(fd, unknown); 1854 } 1855 1856 writeCStr(fd, line); 1857 if (!code.isNative() && code.lnotab().isBytes()) { 1858 byte buf[kUwordDigits10]; 1859 byte* end = buf + kUwordDigits10; 1860 byte* start = end; 1861 word pc = Utils::maximum(frame->virtualPC() - kCodeUnitSize, word{0}); 1862 word linenum = code.offsetToLineNum(pc); 1863 DCHECK(linenum > 0, "expected non-negative line number"); 1864 start = uwordToDecimal(static_cast<uword>(linenum), start); 1865 File::write(fd, start, end - start); 1866 } else { 1867 writeCStr(fd, unknown); 1868 } 1869 1870 writeCStr(fd, in); 1871 RawObject name = function.name(); 1872 if (name.isStr()) { 1873 writeStr(fd, RawStr::cast(name)); 1874 } else { 1875 writeCStr(fd, unknown); 1876 } 1877 } else { 1878 writeCStr(fd, unknown); 1879 writeCStr(fd, line); 1880 writeCStr(fd, unknown); 1881 writeCStr(fd, in); 1882 writeCStr(fd, unknown); 1883 } 1884 1885 writeCStr(fd, "\n"); 1886 frame = frame->previousFrame(); 1887 } 1888 1889 return NoneType::object(); 1890} 1891 1892static RawTuple newEmptyTuple(Heap* heap) { 1893 word size = MutableTuple::allocationSize(0); 1894 uword address; 1895 CHECK(heap->allocate(size, &address), "out of memory"); 1896 return Tuple::cast(MutableTuple::cast(MutableTuple::initialize(address, 0)) 1897 .becomeImmutable()); 1898} 1899 1900void Runtime::initializePrimitiveInstances() { 1901 empty_tuple_ = newEmptyTuple(heap()); 1902 empty_frozen_set_ = newFrozenSet(); 1903 empty_mutable_bytes_ = createMutableBytes(0); 1904 empty_slice_ = newInstanceWithSize(LayoutId::kSlice, Slice::kSize); 1905 { 1906 uword address; 1907 CHECK(heap()->allocate(Ellipsis::allocationSize(), &address), 1908 "out of memory"); 1909 ellipsis_ = Ellipsis::cast(Ellipsis::initialize(address)); 1910 } 1911} 1912 1913void Runtime::initializeInterned(Thread*) { 1914 interned_ = newMutableTuple(kInitialInternSetCapacity); 1915 interned_remaining_ = internSetComputeRemaining(kInitialInternSetCapacity); 1916} 1917 1918void Runtime::initializeSymbols(Thread* thread) { 1919 HandleScope scope(thread); 1920 symbols_ = new Symbols(this); 1921 for (int i = 0; i < static_cast<int>(SymbolId::kMaxId); i++) { 1922 SymbolId id = static_cast<SymbolId>(i); 1923 Object symbol(&scope, symbols()->at(id)); 1924 internStr(thread, symbol); 1925 } 1926} 1927 1928RawObject Runtime::implicitBases() { 1929 return Type::cast(typeAt(LayoutId::kObject)).mro(); 1930} 1931 1932void Runtime::cacheBuildClass(Thread* thread, const Module& builtins) { 1933 HandleScope scope(thread); 1934 Object none(&scope, NoneType::object()); 1935 moduleAtPutById(thread, builtins, ID(__build_class__), none); 1936 build_class_ = moduleValueCellAtById(thread, builtins, ID(__build_class__)); 1937 CHECK(!build_class_.isErrorNotFound(), "__build_class__ not found"); 1938} 1939 1940void Runtime::builtinTypeCreated(Thread* thread, const Type& type) { 1941 LayoutId layout_id = type.instanceLayoutId(); 1942 switch (layout_id) { 1943 case LayoutId::kObject: 1944 object_dunder_class_ = typeAtById(thread, type, ID(__class__)); 1945 object_dunder_eq_ = typeAtById(thread, type, ID(__eq__)); 1946 object_dunder_getattribute_ = 1947 typeAtById(thread, type, ID(__getattribute__)); 1948 object_dunder_hash_ = typeAtById(thread, type, ID(__hash__)); 1949 object_dunder_init_ = typeAtById(thread, type, ID(__init__)); 1950 object_dunder_new_ = typeAtById(thread, type, ID(__new__)); 1951 object_dunder_setattr_ = typeAtById(thread, type, ID(__setattr__)); 1952 type.setFlags(static_cast<Type::Flag>( 1953 type.flags() | Type::Flag::kHasObjectDunderGetattribute | 1954 Type::Flag::kHasObjectDunderNew | Type::Flag::kHasObjectDunderHash)); 1955 break; 1956 case LayoutId::kModule: 1957 module_dunder_getattribute_ = 1958 typeAtById(thread, type, ID(__getattribute__)); 1959 type.setFlags(static_cast<Type::Flag>( 1960 type.flags() | Type::Flag::kHasModuleDunderGetattribute)); 1961 break; 1962 case LayoutId::kNoneType: 1963 // NoneType.__class__ does *not* point to the same object as 1964 // object.__class_ to avoid descriptor resolution for NoneType, but their 1965 // observable behaviors are same. See the definition of NoneType in 1966 // builtins.py. 1967 type.setFlags(static_cast<Type::Flag>(type.flags() | 1968 Type::Flag::kHasObjectDunderClass)); 1969 break; 1970 case LayoutId::kStr: 1971 str_dunder_eq_ = typeAtById(thread, type, ID(__eq__)); 1972 str_dunder_hash_ = typeAtById(thread, type, ID(__hash__)); 1973 type.setFlags(static_cast<Type::Flag>(type.flags() | 1974 Type::Flag::kHasStrDunderHash)); 1975 break; 1976 case LayoutId::kType: 1977 type_dunder_getattribute_ = 1978 typeAtById(thread, type, ID(__getattribute__)); 1979 type.setFlags(static_cast<Type::Flag>( 1980 type.flags() | Type::Flag::kHasTypeDunderGetattribute)); 1981 break; 1982 default: 1983 break; 1984 } 1985 1986 HandleScope scope(thread); 1987 Function dunder_getattribute( 1988 &scope, typeLookupInMroById(thread, *type, ID(__getattribute__))); 1989 // This detects two instances of `object.__getattribute__`: 1990 // 1) Manually created `object.__getattribute__` before initializing `object`. 1991 // 2) Real `object.__getattribute__` after. 1992 if (Str::cast(dunder_getattribute.qualname()) 1993 .equalsCStr("object.__getattribute__")) { 1994 type.setFlags(static_cast<Type::Flag>( 1995 type.flags() | Type::Flag::kHasObjectDunderGetattribute)); 1996 } 1997 1998 Object dunder_new(&scope, typeLookupInMroById(thread, *type, ID(__new__))); 1999 if (*dunder_new == object_dunder_new_ || 2000 // __new__ cannot be found in this type and this type is initialized 2001 // before `object`. 2002 (dunder_new.isErrorNotFound() && object_dunder_new_.isNoneType())) { 2003 type.setFlags(static_cast<Type::Flag>(type.flags() | 2004 Type::Flag::kHasObjectDunderNew)); 2005 } 2006 2007 Object dunder_hash(&scope, typeLookupInMroById(thread, *type, ID(__hash__))); 2008 if (*dunder_hash == object_dunder_hash_ || 2009 // __hash__ cannot be found in this type and this type is initialized 2010 // before `object`. 2011 (dunder_hash.isErrorNotFound() && object_dunder_hash_.isNoneType())) { 2012 type.setFlags(static_cast<Type::Flag>(type.flags() | 2013 Type::Flag::kHasObjectDunderHash)); 2014 } 2015 2016 if (!typeLookupInMroById(thread, *type, ID(__bool__)).isErrorNotFound()) { 2017 type.setFlags( 2018 static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderBool)); 2019 } 2020 2021 if (!typeLookupInMroById(thread, *type, ID(__len__)).isErrorNotFound()) { 2022 type.setFlags( 2023 static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderLen)); 2024 } 2025 2026 Object dunder_class(&scope, 2027 typeLookupInMroById(thread, *type, ID(__class__))); 2028 if (*dunder_class == object_dunder_class_ || 2029 // __class__ cannot be found in this type and this type is initialized 2030 // before `object`. 2031 (dunder_class.isErrorNotFound() && object_dunder_class_.isNoneType())) { 2032 type.setFlags(static_cast<Type::Flag>(type.flags() | 2033 Type::Flag::kHasObjectDunderClass)); 2034 } 2035 2036 Object dunder_eq(&scope, typeLookupInMroById(thread, *type, ID(__eq__))); 2037 if (*dunder_eq == object_dunder_eq_ || 2038 // __eq__ cannot be found in this type and this type is initialized 2039 // before `object`. 2040 (dunder_eq.isErrorNotFound() && object_dunder_eq_.isNoneType())) { 2041 type.setFlags( 2042 static_cast<Type::Flag>(type.flags() | Type::Flag::kHasObjectDunderEq)); 2043 } 2044 2045 if (!typeLookupInMroById(thread, *type, ID(__get__)).isErrorNotFound()) { 2046 type.setFlags( 2047 static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderGet)); 2048 } 2049 2050 if (!typeLookupInMroById(thread, *type, ID(__set__)).isErrorNotFound()) { 2051 type.setFlags( 2052 static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderSet)); 2053 } 2054 2055 if (!typeLookupInMroById(thread, *type, ID(__delete__)).isErrorNotFound()) { 2056 type.setFlags( 2057 static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderDelete)); 2058 } 2059} 2060 2061void Runtime::cacheSysInstances(Thread* thread, const Module& sys) { 2062 sys_stderr_ = moduleValueCellAtById(thread, sys, ID(stderr)); 2063 CHECK(!sys_stderr_.isErrorNotFound(), "sys.stderr not found"); 2064 sys_stdin_ = moduleValueCellAtById(thread, sys, ID(stdin)); 2065 CHECK(!sys_stdin_.isErrorNotFound(), "sys.stdin not found"); 2066 sys_stdout_ = moduleValueCellAtById(thread, sys, ID(stdout)); 2067 CHECK(!sys_stdout_.isErrorNotFound(), "sys.stdout not found"); 2068 display_hook_ = moduleValueCellAtById(thread, sys, ID(displayhook)); 2069 CHECK(!display_hook_.isErrorNotFound(), "sys.displayhook not found"); 2070} 2071 2072void Runtime::visitRootsWithoutApiHandles(PointerVisitor* visitor) { 2073 visitRuntimeRoots(visitor); 2074 visitThreadRoots(visitor); 2075} 2076 2077void Runtime::visitRuntimeRoots(PointerVisitor* visitor) { 2078 // Visit builtin layouts 2079 for (word i = 0; i <= static_cast<word>(LayoutId::kLastBuiltinId); ++i) { 2080 visitor->visitPointer( 2081 reinterpret_cast<RawObject*>(Tuple::cast(layouts_).address() + 2082 i * kPointerSize), 2083 PointerKind::kLayout); 2084 } 2085 2086 // Visit internal types that are not described by a layout 2087 visitor->visitPointer(&large_bytes_, PointerKind::kRuntime); 2088 visitor->visitPointer(&large_int_, PointerKind::kRuntime); 2089 visitor->visitPointer(&large_str_, PointerKind::kRuntime); 2090 visitor->visitPointer(&small_bytes_, PointerKind::kRuntime); 2091 visitor->visitPointer(&small_int_, PointerKind::kRuntime); 2092 visitor->visitPointer(&small_str_, PointerKind::kRuntime); 2093 2094 // Visit instances 2095 visitor->visitPointer(&build_class_, PointerKind::kRuntime); 2096 visitor->visitPointer(&display_hook_, PointerKind::kRuntime); 2097 visitor->visitPointer(&ellipsis_, PointerKind::kRuntime); 2098 visitor->visitPointer(&empty_frozen_set_, PointerKind::kRuntime); 2099 visitor->visitPointer(&empty_mutable_bytes_, PointerKind::kRuntime); 2100 visitor->visitPointer(&empty_slice_, PointerKind::kRuntime); 2101 visitor->visitPointer(&empty_tuple_, PointerKind::kRuntime); 2102 visitor->visitPointer(&module_dunder_getattribute_, PointerKind::kRuntime); 2103 visitor->visitPointer(&object_dunder_class_, PointerKind::kRuntime); 2104 visitor->visitPointer(&object_dunder_eq_, PointerKind::kRuntime); 2105 visitor->visitPointer(&object_dunder_getattribute_, PointerKind::kRuntime); 2106 visitor->visitPointer(&object_dunder_hash_, PointerKind::kRuntime); 2107 visitor->visitPointer(&object_dunder_init_, PointerKind::kRuntime); 2108 visitor->visitPointer(&object_dunder_new_, PointerKind::kRuntime); 2109 visitor->visitPointer(&object_dunder_setattr_, PointerKind::kRuntime); 2110 visitor->visitPointer(&str_dunder_eq_, PointerKind::kRuntime); 2111 visitor->visitPointer(&str_dunder_hash_, PointerKind::kRuntime); 2112 visitor->visitPointer(&sys_stderr_, PointerKind::kRuntime); 2113 visitor->visitPointer(&sys_stdin_, PointerKind::kRuntime); 2114 visitor->visitPointer(&sys_stdout_, PointerKind::kRuntime); 2115 visitor->visitPointer(&type_dunder_getattribute_, PointerKind::kRuntime); 2116 2117 // Visit interned strings. 2118 visitor->visitPointer(&interned_, PointerKind::kRuntime); 2119 2120 // Visit modules 2121 visitor->visitPointer(&modules_, PointerKind::kRuntime); 2122 2123 // Visit symbols 2124 symbols_->visit(visitor); 2125 2126 // Visit GC callbacks 2127 visitor->visitPointer(&callbacks_, PointerKind::kRuntime); 2128 2129 // Visit signal callbacks 2130 visitor->visitPointer(&signal_callbacks_, PointerKind::kRuntime); 2131 2132 visitor->visitPointer(&profiling_new_thread_, PointerKind::kRuntime); 2133 visitor->visitPointer(&profiling_call_, PointerKind::kRuntime); 2134 visitor->visitPointer(&profiling_return_, PointerKind::kRuntime); 2135 2136 // Visit finalizable native instances 2137 visitor->visitPointer(&finalizable_references_, PointerKind::kRuntime); 2138} 2139 2140void Runtime::visitThreadRoots(PointerVisitor* visitor) { 2141 MutexGuard lock(&threads_mutex_); 2142 for (Thread* thread = main_thread_; thread != nullptr; 2143 thread = thread->next()) { 2144 thread->visitRoots(visitor); 2145 } 2146} 2147 2148RawObject Runtime::findModule(const Object& name) { 2149 // TODO(T53728922) it is possible to create modules with non-str names. 2150 DCHECK(name.isStr(), "name not a string"); 2151 2152 Thread* thread = Thread::current(); 2153 HandleScope scope(thread); 2154 Dict dict(&scope, modules()); 2155 Str name_str(&scope, *name); 2156 return dictAtByStr(thread, dict, name_str); 2157} 2158 2159RawObject Runtime::findModuleById(SymbolId name) { 2160 HandleScope scope(Thread::current()); 2161 Object name_obj(&scope, symbols()->at(name)); 2162 return findModule(name_obj); 2163} 2164 2165RawObject Runtime::lookupNameInModule(Thread* thread, SymbolId module_name, 2166 SymbolId name) { 2167 HandleScope scope(thread); 2168 Object module_obj(&scope, findModuleById(module_name)); 2169 DCHECK(!module_obj.isNoneType(), 2170 "The given module '%s' doesn't exist in modules dict", 2171 Symbols::predefinedSymbolAt(module_name)); 2172 Module module(&scope, *module_obj); 2173 return moduleAtById(thread, module, name); 2174} 2175 2176void Runtime::initializeModules(Thread* thread) { 2177 // This function initializes module data that is fixed at compile time of the 2178 // runtime (code, most functions, types, platform name, ...). 2179 // Variable data should NOT be initialize here (runtime executable path, 2180 // PYTHONPATH, sys.flags, ...) 2181 2182 modules_ = newDict(); 2183 for (SymbolId id : kRequiredModules) { 2184 CHECK(!ensureBuiltinModuleById(thread, id).isErrorException(), 2185 "failed to initialize built-in module %s", 2186 Symbols::predefinedSymbolAt(id)); 2187 } 2188} 2189 2190RawObject Runtime::initialize(Thread* thread) { 2191 RawObject result = thread->invokeFunction0(ID(builtins), ID(_init)); 2192 initialized_ = true; 2193 return result; 2194} 2195 2196RawObject Runtime::concreteTypeAt(LayoutId layout_id) { 2197 switch (layout_id) { 2198 case LayoutId::kLargeBytes: 2199 return large_bytes_; 2200 case LayoutId::kLargeInt: 2201 return large_int_; 2202 case LayoutId::kLargeStr: 2203 return large_str_; 2204 case LayoutId::kSmallBytes: 2205 return small_bytes_; 2206 case LayoutId::kSmallInt: 2207 return small_int_; 2208 case LayoutId::kSmallStr: 2209 return small_str_; 2210 default: 2211 return Layout::cast(layoutAt(layout_id)).describedType(); 2212 } 2213} 2214 2215void Runtime::setLargeBytesType(const Type& type) { large_bytes_ = *type; } 2216 2217void Runtime::setLargeIntType(const Type& type) { large_int_ = *type; } 2218 2219void Runtime::setLargeStrType(const Type& type) { large_str_ = *type; } 2220 2221void Runtime::setSmallBytesType(const Type& type) { small_bytes_ = *type; } 2222 2223void Runtime::setSmallIntType(const Type& type) { small_int_ = *type; } 2224 2225void Runtime::setSmallStrType(const Type& type) { small_str_ = *type; } 2226 2227void Runtime::reinitInterpreter() { 2228 // TODO(T79826701) We should interrupt/sync all threads here. 2229 2230 MutexGuard lock(&threads_mutex_); 2231 for (Thread* thread = main_thread_; thread != nullptr; 2232 thread = thread->next()) { 2233 thread->interrupt(Thread::kReinitInterpreter); 2234 } 2235} 2236 2237void Runtime::setProfiling(const Object& new_thread_func, 2238 const Object& call_func, const Object& return_func) { 2239 profiling_new_thread_ = *new_thread_func; 2240 profiling_call_ = *call_func; 2241 profiling_return_ = *return_func; 2242} 2243 2244void Runtime::layoutAtPut(LayoutId layout_id, RawObject object) { 2245 MutableTuple::cast(layouts_).atPut(static_cast<word>(layout_id), object); 2246} 2247 2248RawObject Runtime::typeAt(LayoutId layout_id) { 2249 return Layout::cast(layoutAt(layout_id)).describedType(); 2250} 2251 2252LayoutId Runtime::reserveLayoutId(Thread* thread) { 2253 word result = num_layouts_++; 2254 CHECK(result < Header::kMaxLayoutId, "layout id overflow"); 2255 word length = Tuple::cast(layouts_).length(); 2256 if (result >= length) { 2257 HandleScope scope(thread); 2258 Tuple old_tuple(&scope, layouts_); 2259 word new_length = newCapacity(length, kInitialLayoutTupleCapacity); 2260 MutableTuple new_tuple(&scope, newMutableTuple(new_length)); 2261 new_tuple.replaceFromWith(0, *old_tuple, length); 2262 layouts_ = *new_tuple; 2263 } 2264 return static_cast<LayoutId>(result); 2265} 2266 2267word Runtime::reserveModuleId() { 2268 // TODO(T58039604): Come up with a scheme to reuse deallocated module IDs if 2269 // we run out. 2270 CHECK(max_module_id_ < RawModule::kMaxModuleId, "exceeded module ID space"); 2271 return ++max_module_id_; 2272} 2273 2274word Runtime::newCapacity(word curr_capacity, word min_capacity) { 2275 word new_capacity = (curr_capacity < kInitialEnsuredCapacity) 2276 ? kInitialEnsuredCapacity 2277 : curr_capacity + (curr_capacity >> 1); 2278 if (new_capacity < min_capacity) { 2279 return min_capacity; 2280 } 2281 return Utils::minimum(new_capacity, SmallInt::kMaxValue); 2282} 2283 2284// Bytearray 2285 2286void Runtime::bytearrayEnsureCapacity(Thread* thread, const Bytearray& array, 2287 word min_capacity) { 2288 DCHECK_BOUND(min_capacity, SmallInt::kMaxValue); 2289 word curr_capacity = array.capacity(); 2290 if (min_capacity <= curr_capacity) return; 2291 word new_capacity = newCapacity(curr_capacity, min_capacity); 2292 HandleScope scope(thread); 2293 MutableBytes old_bytes(&scope, array.items()); 2294 MutableBytes new_bytes(&scope, newMutableBytesZeroed(new_capacity)); 2295 byte* dst = reinterpret_cast<byte*>(new_bytes.address()); 2296 word old_length = array.numItems(); 2297 old_bytes.copyTo(dst, old_length); 2298 array.setItems(*new_bytes); 2299} 2300 2301void Runtime::bytearrayExtend(Thread* thread, const Bytearray& array, 2302 View<byte> view) { 2303 word length = view.length(); 2304 if (length == 0) return; 2305 word num_items = array.numItems(); 2306 word new_length = num_items + length; 2307 bytearrayEnsureCapacity(thread, array, new_length); 2308 byte* dst = 2309 reinterpret_cast<byte*>(MutableBytes::cast(array.items()).address()); 2310 std::memcpy(dst + num_items, view.data(), view.length()); 2311 array.setNumItems(new_length); 2312} 2313 2314void Runtime::bytearrayIadd(Thread* thread, const Bytearray& array, 2315 const Bytes& bytes, word length) { 2316 DCHECK_BOUND(length, bytes.length()); 2317 if (length == 0) return; 2318 word num_items = array.numItems(); 2319 word new_length = num_items + length; 2320 bytearrayEnsureCapacity(thread, array, new_length); 2321 MutableBytes::cast(array.items()) 2322 .replaceFromWithBytes(num_items, *bytes, length); 2323 array.setNumItems(new_length); 2324} 2325 2326// Bytes 2327 2328RawObject Runtime::bytesConcat(Thread* thread, const Bytes& left, 2329 const Bytes& right) { 2330 word left_len = left.length(); 2331 word right_len = right.length(); 2332 word len = left_len + right_len; 2333 if (len <= SmallBytes::kMaxLength) { 2334 byte buffer[SmallBytes::kMaxLength]; 2335 left.copyTo(buffer, left_len); 2336 right.copyTo(buffer + left_len, right_len); 2337 return SmallBytes::fromBytes({buffer, len}); 2338 } 2339 HandleScope scope(thread); 2340 MutableBytes result(&scope, newMutableBytesUninitialized(len)); 2341 result.replaceFromWithBytes(0, *left, left_len); 2342 result.replaceFromWithBytes(left_len, *right, right_len); 2343 return result.becomeImmutable(); 2344} 2345 2346RawObject Runtime::bytesCopy(Thread* thread, const Bytes& src) { 2347 if (src.isSmallBytes()) return *src; 2348 return bytesSubseq(thread, src, 0, src.length()); 2349} 2350 2351RawObject Runtime::bytesCopyWithSize(Thread* thread, const Bytes& original, 2352 word new_length) { 2353 DCHECK(new_length >= 0, "length must be nonnegative"); 2354 if (new_length == 0) return Bytes::empty(); 2355 word old_length = original.length(); 2356 if (new_length <= SmallBytes::kMaxLength) { 2357 byte buffer[SmallBytes::kMaxLength]; 2358 original.copyTo(buffer, Utils::minimum(old_length, new_length)); 2359 return SmallBytes::fromBytes({buffer, new_length}); 2360 } 2361 HandleScope scope(thread); 2362 MutableBytes copy(&scope, newMutableBytesUninitialized(new_length)); 2363 if (old_length < new_length) { 2364 copy.replaceFromWithBytes(0, *original, old_length); 2365 copy.replaceFromWithByte(old_length, 0, new_length - old_length); 2366 } else { 2367 copy.replaceFromWith(0, LargeBytes::cast(*original), new_length); 2368 } 2369 return copy.becomeImmutable(); 2370} 2371 2372RawObject Runtime::bytesEndsWith(const Bytes& bytes, word bytes_len, 2373 const Bytes& suffix, word suffix_len, 2374 word start, word end) { 2375 DCHECK_BOUND(bytes_len, bytes.length()); 2376 DCHECK_BOUND(suffix_len, suffix.length()); 2377 Slice::adjustSearchIndices(&start, &end, bytes_len); 2378 if (end - start < suffix_len || start > bytes_len) { 2379 return Bool::falseObj(); 2380 } 2381 for (word i = end - suffix_len, j = 0; i < end; i++, j++) { 2382 if (bytes.byteAt(i) != suffix.byteAt(j)) { 2383 return Bool::falseObj(); 2384 } 2385 } 2386 return Bool::trueObj(); 2387} 2388 2389RawObject Runtime::bytesFromTuple(Thread* thread, const Tuple& items, 2390 word length) { 2391 DCHECK_BOUND(length, items.length()); 2392 HandleScope scope(thread); 2393 MutableBytes result(&scope, empty_mutable_bytes_); 2394 byte buffer[SmallBytes::kMaxLength]; 2395 byte* dst; 2396 if (length <= SmallBytes::kMaxLength) { 2397 dst = buffer; 2398 } else { 2399 result = newMutableBytesUninitialized(length); 2400 dst = reinterpret_cast<byte*>(MutableBytes::cast(*result).address()); 2401 } 2402 for (word idx = 0; idx < length; idx++) { 2403 Object item(&scope, items.at(idx)); 2404 if (!isInstanceOfInt(*item)) { 2405 // escape into slow path 2406 return NoneType::object(); 2407 } 2408 OptInt<byte> current_byte = intUnderlying(*item).asInt<byte>(); 2409 if (current_byte.error == CastError::None) { 2410 dst[idx] = current_byte.value; 2411 } else { 2412 // TODO(T55871582): Move error handling to caller 2413 return thread->raiseWithFmt(LayoutId::kValueError, 2414 "bytes must be in range(0, 256)"); 2415 } 2416 } 2417 return length <= SmallBytes::kMaxLength 2418 ? SmallBytes::fromBytes({buffer, length}) 2419 : result.becomeImmutable(); 2420} 2421 2422RawObject Runtime::bytesRepeat(Thread* thread, const Bytes& source, word length, 2423 word count) { 2424 DCHECK_BOUND(length, source.length()); 2425 DCHECK_BOUND(count, kMaxWord / length); 2426 if (count == 0 || length == 0) { 2427 return Bytes::empty(); 2428 } 2429 bool is_mutable = source.isMutableBytes(); 2430 if (length == 1) { 2431 byte item = source.byteAt(0); 2432 return is_mutable ? mutableBytesWith(count, item) : newBytes(count, item); 2433 } 2434 word new_length = length * count; 2435 if (!is_mutable && new_length <= SmallBytes::kMaxLength) { 2436 byte buffer[SmallBytes::kMaxLength]; 2437 byte* dst = buffer; 2438 for (word i = 0; i < count; i++, dst += length) { 2439 source.copyTo(dst, length); 2440 } 2441 return SmallBytes::fromBytes({buffer, new_length}); 2442 } 2443 HandleScope scope(thread); 2444 MutableBytes result(&scope, newMutableBytesUninitialized(new_length)); 2445 for (word i = 0; i < count * length; i += length) { 2446 result.replaceFromWithBytes(i, *source, length); 2447 } 2448 return is_mutable ? *result : result.becomeImmutable(); 2449} 2450 2451RawObject Runtime::bytesReplace(Thread* thread, const Bytes& src, 2452 const Bytes& old_bytes, word old_len, 2453 const Bytes& new_bytes, word new_len, 2454 word max_count) { 2455 word src_len = src.length(); 2456 if (max_count == 0 || src_len == 0 || old_bytes.compare(*new_bytes) == 0) { 2457 return *src; 2458 } 2459 // Update the max_count to the number of occurences of old_bytes in src, 2460 // capped by the given max_count 2461 word count = bytesCount(src, src_len, old_bytes, old_len, 0, src_len); 2462 if (max_count < 0 || max_count > count) { 2463 max_count = count; 2464 } 2465 if (max_count == 0) { 2466 return *src; 2467 } 2468 2469 HandleScope scope(thread); 2470 word result_len = src_len + (new_len - old_len) * max_count; 2471 MutableBytes result(&scope, newMutableBytesUninitialized(result_len)); 2472 2473 byte src_buffer[SmallBytes::kMaxLength], old_buffer[SmallBytes::kMaxLength]; 2474 byte *src_ptr, *old_ptr; 2475 if (src.isLargeBytes()) { 2476 src_ptr = reinterpret_cast<byte*>(LargeBytes::cast(*src).address()); 2477 } else { 2478 src.copyTo(src_buffer, src_len); 2479 src_ptr = src_buffer; 2480 } 2481 if (old_bytes.isLargeBytes()) { 2482 old_ptr = reinterpret_cast<byte*>(LargeBytes::cast(*old_bytes).address()); 2483 } else { 2484 old_bytes.copyTo(old_buffer, old_len); 2485 old_ptr = old_buffer; 2486 } 2487 2488 word dst_idx = 0, src_idx = 0; 2489 for (; max_count > 0; max_count--) { 2490 byte* found_ptr = reinterpret_cast<byte*>( 2491 ::memmem(src_ptr + src_idx, src_len - src_idx, old_ptr, old_len)); 2492 word prefix_len = found_ptr - (src_ptr + src_idx); 2493 result.replaceFromWithBytesStartAt(dst_idx, *src, prefix_len, src_idx); 2494 dst_idx += prefix_len; 2495 result.replaceFromWithBytesStartAt(dst_idx, *new_bytes, new_len, 0); 2496 dst_idx += new_len; 2497 src_idx += prefix_len + old_len; 2498 } 2499 result.replaceFromWithBytesStartAt(dst_idx, *src, src_len - src_idx, src_idx); 2500 return result.becomeImmutable(); 2501} 2502 2503static void writeByteslikeRepr(const Byteslike& byteslike, byte* dst, 2504 word result_length, byte delimiter) { 2505 byte* ptr = dst; 2506 *ptr++ = 'b'; 2507 *ptr++ = delimiter; 2508 2509 word length = byteslike.length(); 2510 for (word i = 0; i < length; i++) { 2511 byte current = byteslike.byteAt(i); 2512 if (current == delimiter || current == '\\') { 2513 *ptr++ = '\\'; 2514 *ptr++ = current; 2515 } else if (current == '\t') { 2516 *ptr++ = '\\'; 2517 *ptr++ = 't'; 2518 } else if (current == '\n') { 2519 *ptr++ = '\\'; 2520 *ptr++ = 'n'; 2521 } else if (current == '\r') { 2522 *ptr++ = '\\'; 2523 *ptr++ = 'r'; 2524 } else if (ASCII::isPrintable(current)) { 2525 *ptr++ = current; 2526 } else { 2527 *ptr++ = '\\'; 2528 *ptr++ = 'x'; 2529 uwordToHexadecimal(ptr, /*num_digits=*/2, current); 2530 ptr += 2; 2531 } 2532 } 2533 *ptr++ = delimiter; 2534 DCHECK(ptr - dst == result_length, "precalculated repr length was incorrect"); 2535} 2536 2537RawObject Runtime::byteslikeRepr(Thread* thread, const Byteslike& byteslike, 2538 word result_length, byte delimiter) { 2539 if (result_length <= SmallStr::kMaxLength) { 2540 byte buffer[SmallStr::kMaxLength]; 2541 writeByteslikeRepr(byteslike, buffer, result_length, delimiter); 2542 return SmallStr::fromBytes({buffer, result_length}); 2543 } 2544 2545 HandleScope scope(thread); 2546 LargeStr result(&scope, createLargeStr(result_length)); 2547 writeByteslikeRepr(byteslike, reinterpret_cast<byte*>(result.address()), 2548 result_length, delimiter); 2549 return *result; 2550} 2551 2552RawObject Runtime::bytesSlice(Thread* thread, const Bytes& bytes, word start, 2553 word stop, word step) { 2554 word length = Slice::length(start, stop, step); 2555 if (length <= SmallBytes::kMaxLength) { 2556 byte buffer[SmallBytes::kMaxLength]; 2557 for (word i = 0, j = start; i < length; i++, j += step) { 2558 buffer[i] = bytes.byteAt(j); 2559 } 2560 return SmallBytes::fromBytes({buffer, length}); 2561 } 2562 HandleScope scope(thread); 2563 MutableBytes result(&scope, newMutableBytesUninitialized(length)); 2564 { 2565 byte* dst = reinterpret_cast<byte*>(result.address()); 2566 for (word i = 0, j = start; i < length; i++, j += step) { 2567 dst[i] = bytes.byteAt(j); 2568 } 2569 } 2570 return result.becomeImmutable(); 2571} 2572 2573RawObject Runtime::bytesStartsWith(const Bytes& bytes, word bytes_len, 2574 const Bytes& prefix, word prefix_len, 2575 word start, word end) { 2576 DCHECK_BOUND(bytes_len, bytes.length()); 2577 DCHECK_BOUND(prefix_len, prefix.length()); 2578 Slice::adjustSearchIndices(&start, &end, bytes_len); 2579 if (start + prefix_len > end) { 2580 return Bool::falseObj(); 2581 } 2582 for (word i = start, j = 0; j < prefix_len; i++, j++) { 2583 if (bytes.byteAt(i) != prefix.byteAt(j)) { 2584 return Bool::falseObj(); 2585 } 2586 } 2587 return Bool::trueObj(); 2588} 2589 2590RawObject Runtime::bytesTranslate(Thread* thread, const Bytes& bytes, 2591 word length, const Bytes& table, 2592 word table_len, const Bytes& del, 2593 word del_len) { 2594 DCHECK_BOUND(length, bytes.length()); 2595 DCHECK_BOUND(del_len, del.length()); 2596 // calculate mapping table 2597 byte new_byte[kByteTranslationTableLength]; 2598 if (table == Bytes::empty()) { 2599 for (word i = 0; i < kByteTranslationTableLength; i++) { 2600 new_byte[i] = i; 2601 } 2602 } else { 2603 DCHECK_BOUND(table_len, table.length()); 2604 DCHECK(table_len == kByteTranslationTableLength, 2605 "translation table must map every possible byte value"); 2606 for (word i = 0; i < kByteTranslationTableLength; i++) { 2607 new_byte[i] = table.byteAt(i); 2608 } 2609 } 2610 // make initial pass to calculate length 2611 bool delete_byte[kByteTranslationTableLength] = {}; 2612 for (word i = 0; i < del_len; i++) { 2613 delete_byte[del.byteAt(i)] = true; 2614 } 2615 word new_length = length; 2616 for (word i = 0; i < length; i++) { 2617 if (delete_byte[bytes.byteAt(i)]) { 2618 new_length--; 2619 } 2620 } 2621 // replace or delete each byte 2622 bool is_mutable = bytes.isMutableBytes(); 2623 if (new_length <= SmallBytes::kMaxLength && !is_mutable) { 2624 byte buffer[SmallBytes::kMaxLength]; 2625 for (word i = 0, j = 0; j < new_length; i++) { 2626 DCHECK(i < length, "reached end of bytes before finishing translation"); 2627 byte current = bytes.byteAt(i); 2628 if (!delete_byte[current]) { 2629 buffer[j++] = new_byte[current]; 2630 } 2631 } 2632 return SmallBytes::fromBytes({buffer, new_length}); 2633 } 2634 HandleScope scope(thread); 2635 MutableBytes result(&scope, newMutableBytesUninitialized(new_length)); 2636 for (word i = 0, j = 0; j < new_length; i++) { 2637 DCHECK(i < length, "reached end of bytes before finishing translation"); 2638 byte current = bytes.byteAt(i); 2639 if (!delete_byte[current]) { 2640 result.byteAtPut(j++, new_byte[current]); 2641 } 2642 } 2643 return is_mutable ? *result : result.becomeImmutable(); 2644} 2645 2646// List 2647 2648void Runtime::listEnsureCapacity(Thread* thread, const List& list, 2649 word min_capacity) { 2650 DCHECK_BOUND(min_capacity, SmallInt::kMaxValue); 2651 word curr_capacity = list.capacity(); 2652 if (min_capacity <= curr_capacity) return; 2653 word new_capacity = newCapacity(curr_capacity, min_capacity); 2654 HandleScope scope(thread); 2655 Tuple old_array(&scope, list.items()); 2656 MutableTuple new_array(&scope, newMutableTuple(new_capacity)); 2657 new_array.replaceFromWith(0, *old_array, list.numItems()); 2658 list.setItems(*new_array); 2659} 2660 2661void Runtime::listAdd(Thread* thread, const List& list, const Object& value) { 2662 word index = list.numItems(); 2663 listEnsureCapacity(thread, list, index + 1); 2664 list.setNumItems(index + 1); 2665 list.atPut(index, *value); 2666} 2667 2668// Dict 2669 2670RawObject Runtime::newDict() { 2671 word num_attributes = Dict::kSize / kPointerSize; 2672 word size = Instance::allocationSize(num_attributes); 2673 uword address; 2674 CHECK(heap()->allocate(size, &address), "out of memory"); 2675 return Instance::initializeWithZero(address, num_attributes, LayoutId::kDict); 2676} 2677 2678RawObject Runtime::newDictWithSize(word initial_size) { 2679 Thread* thread = Thread::current(); 2680 HandleScope scope(thread); 2681 // NOTE: Multiplying 2 will leave (initial_size * 2 * 2/3) - initial_size 2682 // items available after initial_size items are inserted before dict is 2683 // expanded. 2684 word indices_len = Utils::nextPowerOfTwo(initial_size) * 2; 2685 Dict dict(&scope, newDict()); 2686 dictAllocateArrays(thread, dict, indices_len); 2687 return *dict; 2688} 2689 2690static RawObject NEVER_INLINE callDunderEq(Thread* thread, RawObject o0_raw, 2691 RawObject o1_raw) { 2692 HandleScope scope(thread); 2693 Object o0(&scope, o0_raw); 2694 Object o1(&scope, o1_raw); 2695 Runtime* runtime = thread->runtime(); 2696 Type o0_type(&scope, runtime->typeOf(*o0)); 2697 Type o1_type(&scope, runtime->typeOf(*o1)); 2698 if ((o0_type.flags() & Type::Flag::kHasObjectDunderEq) && 2699 (o1_type.flags() & Type::Flag::kHasObjectDunderEq)) { 2700 return Bool::fromBool(*o0 == *o1); 2701 } 2702 Object compare_result( 2703 &scope, Interpreter::compareOperation(thread, CompareOp::EQ, o0, o1)); 2704 if (compare_result.isErrorException()) return *compare_result; 2705 Object result(&scope, Interpreter::isTrue(thread, *compare_result)); 2706 if (result.isErrorException()) return *result; 2707 return *result; 2708} 2709 2710RawObject Runtime::objectEquals(Thread* thread, RawObject o0, RawObject o1) { 2711 if (o0 == o1) { 2712 return Bool::trueObj(); 2713 } 2714 // Shortcuts to catch the common SmallStr, LargeStr and SmallInt cases. 2715 // Remember that we always have to check the layout/type of `o0` and `o1` 2716 // to ensure `o1` is not a subclass of `o0` which would result in a 2717 // `o1.__eq__(o0)` call. 2718 if (!o0.isHeapObject()) { 2719 if (o1.isLargeStr()) { 2720 return Bool::falseObj(); 2721 } 2722 if (!o1.isHeapObject()) { 2723 if (o0.layoutId() != o1.layoutId()) { 2724 if (o0.isBool() && o1.isSmallInt()) { 2725 return Bool::fromBool((Bool::cast(o0).value() ? 1 : 0) == 2726 SmallInt::cast(o1).value()); 2727 } 2728 if (o0.isSmallInt() && o1.isBool()) { 2729 return Bool::fromBool(SmallInt::cast(o0).value() == 2730 (Bool::cast(o1).value() ? 1 : 0)); 2731 } 2732 } 2733 return Bool::falseObj(); 2734 } 2735 } else if (o0.isLargeStr()) { 2736 if (o1.isLargeStr()) { 2737 return Bool::fromBool(LargeStr::cast(o0).equals(LargeStr::cast(o1))); 2738 } 2739 if (!o1.isHeapObject()) { 2740 return Bool::falseObj(); 2741 } 2742 } 2743 return callDunderEq(thread, o0, o1); 2744} 2745 2746// DictItemIterator 2747 2748RawObject Runtime::newDictItemIterator(Thread* thread, const Dict& dict) { 2749 HandleScope scope(thread); 2750 DictItemIterator result(&scope, 2751 newInstanceWithSize(LayoutId::kDictItemIterator, 2752 DictItemIterator::kSize)); 2753 result.setIndex(0); 2754 result.setIterable(*dict); 2755 result.setNumFound(0); 2756 return *result; 2757} 2758 2759// DictItems 2760 2761RawObject Runtime::newDictItems(Thread* thread, const Dict& dict) { 2762 HandleScope scope(thread); 2763 DictItems result(&scope, 2764 newInstanceWithSize(LayoutId::kDictItems, DictItems::kSize)); 2765 result.setDict(*dict); 2766 return *result; 2767} 2768 2769// DictKeyIterator 2770 2771RawObject Runtime::newDictKeyIterator(Thread* thread, const Dict& dict) { 2772 HandleScope scope(thread); 2773 DictKeyIterator result(&scope, newInstanceWithSize(LayoutId::kDictKeyIterator, 2774 DictKeyIterator::kSize)); 2775 result.setIndex(0); 2776 result.setIterable(*dict); 2777 result.setNumFound(0); 2778 return *result; 2779} 2780 2781// DictKeys 2782 2783RawObject Runtime::newDictKeys(Thread* thread, const Dict& dict) { 2784 HandleScope scope(thread); 2785 DictKeys result(&scope, 2786 newInstanceWithSize(LayoutId::kDictKeys, DictKeys::kSize)); 2787 result.setDict(*dict); 2788 return *result; 2789} 2790 2791// DictValueIterator 2792 2793RawObject Runtime::newDictValueIterator(Thread* thread, const Dict& dict) { 2794 HandleScope scope(thread); 2795 DictValueIterator result(&scope, 2796 newInstanceWithSize(LayoutId::kDictValueIterator, 2797 DictValueIterator::kSize)); 2798 result.setIndex(0); 2799 result.setIterable(*dict); 2800 result.setNumFound(0); 2801 return *result; 2802} 2803 2804// DictValues 2805 2806RawObject Runtime::newDictValues(Thread* thread, const Dict& dict) { 2807 HandleScope scope(thread); 2808 DictValues result( 2809 &scope, newInstanceWithSize(LayoutId::kDictValues, DictValues::kSize)); 2810 result.setDict(*dict); 2811 return *result; 2812} 2813 2814// Set 2815 2816RawObject Runtime::newSet() { 2817 HandleScope scope(Thread::current()); 2818 Set result(&scope, newInstanceWithSize(LayoutId::kSet, Set::kSize)); 2819 result.setNumItems(0); 2820 result.setNumFilled(0); 2821 result.setData(empty_tuple_); 2822 return *result; 2823} 2824 2825RawObject Runtime::newFrozenSet() { 2826 HandleScope scope(Thread::current()); 2827 FrozenSet result(&scope, 2828 newInstanceWithSize(LayoutId::kFrozenSet, FrozenSet::kSize)); 2829 result.setNumItems(0); 2830 result.setNumFilled(0); 2831 result.setData(empty_tuple_); 2832 return *result; 2833} 2834 2835RawObject Runtime::tupleSubseq(Thread* thread, const Tuple& tuple, word start, 2836 word length) { 2837 DCHECK_BOUND(start, tuple.length()); 2838 DCHECK_BOUND(length, tuple.length() - start); 2839 if (length == 0) return empty_tuple_; 2840 HandleScope scope(thread); 2841 MutableTuple result(&scope, newMutableTuple(length)); 2842 for (word i = 0; i < length; i++) { 2843 result.atPut(i, tuple.at(i + start)); 2844 } 2845 return result.becomeImmutable(); 2846} 2847 2848RawObject Runtime::newValueCell() { 2849 return newInstanceWithSize(LayoutId::kValueCell, ValueCell::kSize); 2850} 2851 2852RawObject Runtime::newWeakLink(Thread* thread, const Object& referent, 2853 const Object& prev, const Object& next) { 2854 HandleScope scope(thread); 2855 DCHECK(referent.isNoneType() || referent.isHeapObject(), 2856 "expected heap object or None"); 2857 WeakLink link(&scope, 2858 newInstanceWithSize(LayoutId::kWeakLink, WeakLink::kSize)); 2859 link.setReferent(*referent); 2860 link.setCallback(NoneType::object()); 2861 link.setPrev(*prev); 2862 link.setNext(*next); 2863 return *link; 2864} 2865 2866RawObject Runtime::newWeakRef(Thread* thread, const Object& referent) { 2867 DCHECK(referent.isNoneType() || referent.isHeapObject(), 2868 "expected heap object or None"); 2869 HandleScope scope(thread); 2870 WeakRef ref(&scope, newInstanceWithSize(LayoutId::kWeakRef, WeakRef::kSize)); 2871 ref.setReferent(*referent); 2872 return *ref; 2873} 2874 2875void Runtime::collectAttributes(const Code& code, const Dict& attributes) { 2876 Thread* thread = Thread::current(); 2877 HandleScope scope(thread); 2878 Bytes bc(&scope, code.code()); 2879 Tuple names(&scope, code.names()); 2880 2881 word len = bc.length(); 2882 word self = 0; 2883 word total_locals = code.nlocals() + code.numFreevars() + code.numCellvars(); 2884 word reverse_self = total_locals - self - 1; 2885 for (word i = 0; i < len - (kCompilerCodeUnitSize + 1); 2886 i += kCompilerCodeUnitSize) { 2887 byte op = bc.byteAt(i); 2888 int32_t arg = bc.byteAt(i + 1); 2889 while (op == Bytecode::EXTENDED_ARG) { 2890 i += kCompilerCodeUnitSize; 2891 op = bc.byteAt(i); 2892 arg = (arg << kBitsPerByte) | bc.byteAt(i + 1); 2893 } 2894 // Check for LOAD_FAST 0 (self) or LOAD_FAST_REVERSE(_UNCHECKED) nlocals-1 2895 bool is_load_self = 2896 (op == Bytecode::LOAD_FAST && arg == self) || 2897 (op == Bytecode::LOAD_FAST_REVERSE && arg == reverse_self) || 2898 (op == Bytecode::LOAD_FAST_REVERSE_UNCHECKED && arg == reverse_self); 2899 if (!is_load_self) { 2900 continue; 2901 } 2902 // Followed by a STORE_ATTR 2903 if (bc.byteAt(i + 2) != Bytecode::STORE_ATTR) { 2904 continue; 2905 } 2906 word name_index = bc.byteAt(i + 3); 2907 Str name(&scope, names.at(name_index)); 2908 dictAtPutByStr(thread, attributes, name, name); 2909 } 2910} 2911 2912RawObject Runtime::classConstructor(const Type& type) { 2913 Thread* thread = Thread::current(); 2914 return typeAtById(thread, type, ID(__init__)); 2915} 2916 2917RawObject Runtime::attributeAt(Thread* thread, const Object& receiver, 2918 const Object& name) { 2919 return attributeAtSetLocation(thread, receiver, name, nullptr, nullptr); 2920} 2921 2922RawObject Runtime::attributeAtSetLocation(Thread* thread, 2923 const Object& receiver, 2924 const Object& name, 2925 LoadAttrKind* kind, 2926 Object* location_out) { 2927 DCHECK(isInternedStr(thread, name), "name must be an interned str"); 2928 HandleScope scope(thread); 2929 Runtime* runtime = thread->runtime(); 2930 Type type(&scope, runtime->typeOf(*receiver)); 2931 if (kind != nullptr) *kind = LoadAttrKind::kUnknown; 2932 if (type.hasFlag(Type::Flag::kHasObjectDunderGetattribute)) { 2933 DCHECK(objectDunderGetattribute().isNoneType() || 2934 typeLookupInMroById(thread, *type, ID(__getattribute__)) == 2935 objectDunderGetattribute(), 2936 "object.__getattribute__ is expected"); 2937 Object result(&scope, objectGetAttributeSetLocation(thread, receiver, name, 2938 location_out, kind)); 2939 if (!result.isErrorNotFound()) { 2940 return *result; 2941 } 2942 result = thread->invokeMethod2(receiver, ID(__getattr__), name); 2943 if (!result.isErrorNotFound()) { 2944 return *result; 2945 } 2946 if (location_out != nullptr && location_out->isUnbound()) { 2947 // hasattr doesn't need the full exception; don't format and raise. 2948 return Error::notFound(); 2949 } 2950 return objectRaiseAttributeError(thread, receiver, name); 2951 } 2952 if (type.hasFlag(Type::Flag::kHasModuleDunderGetattribute) && 2953 runtime->isInstanceOfModule(*receiver)) { 2954 DCHECK(runtime->moduleDunderGetattribute().isNoneType() || 2955 typeLookupInMroById(thread, *type, ID(__getattribute__)) == 2956 runtime->moduleDunderGetattribute(), 2957 "module.__getattribute__ is expected"); 2958 Module module(&scope, *receiver); 2959 Object result(&scope, moduleGetAttributeSetLocation(thread, module, name, 2960 location_out)); 2961 if (!result.isErrorNotFound()) { 2962 // We have a result that can be cached. 2963 if (kind != nullptr) *kind = LoadAttrKind::kModule; 2964 return *result; 2965 } 2966 // Try again 2967 result = thread->invokeMethod2(receiver, ID(__getattr__), name); 2968 if (!result.isErrorNotFound()) { 2969 return *result; 2970 } 2971 if (location_out != nullptr && location_out->isUnbound()) { 2972 // hasattr doesn't need the full exception; don't format and raise. 2973 return Error::notFound(); 2974 } 2975 return moduleRaiseAttributeError(thread, module, name); 2976 } 2977 if (type.hasFlag(Type::Flag::kHasTypeDunderGetattribute) && 2978 runtime->isInstanceOfType(*receiver)) { 2979 DCHECK(runtime->typeDunderGetattribute().isNoneType() || 2980 typeLookupInMroById(thread, *type, ID(__getattribute__)) == 2981 runtime->typeDunderGetattribute(), 2982 "type.__getattribute__ is expected"); 2983 Type object_as_type(&scope, *receiver); 2984 Object result(&scope, typeGetAttributeSetLocation(thread, object_as_type, 2985 name, location_out)); 2986 if (!result.isErrorNotFound()) { 2987 // We have a result that can be cached. 2988 if (kind != nullptr && location_out->isValueCell()) { 2989 *kind = LoadAttrKind::kType; 2990 } 2991 return *result; 2992 } 2993 // Try again 2994 result = thread->invokeMethod2(receiver, ID(__getattr__), name); 2995 if (!result.isErrorNotFound()) { 2996 return *result; 2997 } 2998 if (location_out != nullptr && location_out->isUnbound()) { 2999 // hasattr doesn't need the full exception; don't format and raise. 3000 return Error::notFound(); 3001 } 3002 Object type_name(&scope, object_as_type.name()); 3003 return thread->raiseWithFmt(LayoutId::kAttributeError, 3004 "type object '%S' has no attribute '%S'", 3005 &type_name, &name); 3006 } 3007 if (receiver.isSuper()) { 3008 Super object_as_super(&scope, *receiver); 3009 Object result(&scope, superGetAttribute(thread, object_as_super, name)); 3010 if (!result.isErrorNotFound()) { 3011 return *result; 3012 } 3013 if (location_out != nullptr && location_out->isUnbound()) { 3014 // hasattr doesn't need the full exception; don't format and raise. 3015 return Error::notFound(); 3016 } 3017 return thread->raiseWithFmt(LayoutId::kAttributeError, 3018 "super object has no attribute '%S'", &name); 3019 } 3020 Object dunder_getattribute( 3021 &scope, 3022 Interpreter::lookupMethod(thread, receiver, ID(__getattribute__))); 3023 DCHECK(!dunder_getattribute.isErrorNotFound(), 3024 "__getattribute__ is expected to be found"); 3025 if (UNLIKELY(dunder_getattribute.isError())) return *dunder_getattribute; 3026 Object result(&scope, Interpreter::callMethod2(thread, dunder_getattribute, 3027 receiver, name)); 3028 if (!result.isErrorException() || 3029 !thread->pendingExceptionMatches(LayoutId::kAttributeError)) { 3030 return *result; 3031 } 3032 3033 // Save the attribute error and clear it then attempt to call `__getattr__`. 3034 Object saved_type(&scope, thread->pendingExceptionType()); 3035 Object saved_value(&scope, thread->pendingExceptionValue()); 3036 Object saved_traceback(&scope, thread->pendingExceptionTraceback()); 3037 thread->clearPendingException(); 3038 result = thread->invokeMethod2(receiver, ID(__getattr__), name); 3039 if (result.isErrorNotFound()) { 3040 thread->setPendingExceptionType(*saved_type); 3041 thread->setPendingExceptionValue(*saved_value); 3042 thread->setPendingExceptionTraceback(*saved_traceback); 3043 return Error::exception(); 3044 } 3045 return *result; 3046} 3047 3048RawObject Runtime::attributeAtById(Thread* thread, const Object& receiver, 3049 SymbolId id) { 3050 HandleScope scope(thread); 3051 Object name(&scope, symbols()->at(id)); 3052 return attributeAt(thread, receiver, name); 3053} 3054 3055RawObject Runtime::attributeAtByCStr(Thread* thread, const Object& receiver, 3056 const char* name) { 3057 HandleScope scope(thread); 3058 Object name_obj(&scope, internStrFromCStr(thread, name)); 3059 return attributeAt(thread, receiver, name_obj); 3060} 3061 3062RawObject Runtime::attributeDel(Thread* thread, const Object& receiver, 3063 const Object& name) { 3064 HandleScope scope(thread); 3065 Object dunder_delattr( 3066 &scope, Interpreter::lookupMethod(thread, receiver, ID(__delattr__))); 3067 DCHECK(!dunder_delattr.isErrorNotFound(), 3068 "__delattr__ is expected to be found"); 3069 if (dunder_delattr.isErrorException()) return *dunder_delattr; 3070 return Interpreter::callMethod2(thread, dunder_delattr, receiver, name); 3071} 3072 3073RawObject Runtime::strConcat(Thread* thread, const Str& left, 3074 const Str& right) { 3075 HandleScope scope(thread); 3076 word left_len = left.length(); 3077 word right_len = right.length(); 3078 word result_len = left_len + right_len; 3079 // Small result 3080 if (result_len <= RawSmallStr::kMaxLength) { 3081 byte buffer[RawSmallStr::kMaxLength]; 3082 left.copyTo(buffer, left_len); 3083 right.copyTo(buffer + left_len, right_len); 3084 return SmallStr::fromBytes(View<byte>(buffer, result_len)); 3085 } 3086 // Large result 3087 LargeStr result(&scope, createLargeStr(result_len)); 3088 left.copyTo(reinterpret_cast<byte*>(result.address()), left_len); 3089 right.copyTo(reinterpret_cast<byte*>(result.address() + left_len), right_len); 3090 return *result; 3091} 3092 3093RawObject Runtime::strJoin(Thread* thread, const Str& sep, const Tuple& items, 3094 word allocated) { 3095 HandleScope scope(thread); 3096 word result_len = 0; 3097 Str str(&scope, Str::empty()); 3098 for (word i = 0; i < allocated; ++i) { 3099 str = strUnderlying(items.at(i)); 3100 result_len += str.length(); 3101 } 3102 if (allocated > 1) { 3103 result_len += sep.length() * (allocated - 1); 3104 } 3105 // Small result 3106 Object elt(&scope, NoneType::object()); 3107 if (result_len <= RawSmallStr::kMaxLength) { 3108 byte buffer[RawSmallStr::kMaxLength]; 3109 for (word i = 0, offset = 0; i < allocated; ++i) { 3110 elt = items.at(i); 3111 str = strUnderlying(*elt); 3112 word str_len = str.length(); 3113 str.copyTo(&buffer[offset], str_len); 3114 offset += str_len; 3115 if ((i + 1) < allocated) { 3116 word sep_len = sep.length(); 3117 sep.copyTo(&buffer[offset], sep_len); 3118 offset += sep.length(); 3119 } 3120 } 3121 return SmallStr::fromBytes(View<byte>(buffer, result_len)); 3122 } 3123 // Large result 3124 LargeStr result(&scope, createLargeStr(result_len)); 3125 for (word i = 0, offset = 0; i < allocated; ++i) { 3126 elt = items.at(i); 3127 str = strUnderlying(*elt); 3128 word str_len = str.length(); 3129 str.copyTo(reinterpret_cast<byte*>(result.address() + offset), str_len); 3130 offset += str_len; 3131 if ((i + 1) < allocated) { 3132 word sep_len = sep.length(); 3133 sep.copyTo(reinterpret_cast<byte*>(result.address() + offset), sep_len); 3134 offset += sep_len; 3135 } 3136 } 3137 return *result; 3138} 3139 3140RawObject Runtime::strRepeat(Thread* thread, const Str& str, word count) { 3141 DCHECK(count > 0, "count should be positive"); 3142 byte buffer[SmallStr::kMaxLength]; 3143 word length = str.length(); 3144 DCHECK(length > 0, "length should be positive"); 3145 DCHECK_BOUND(count, SmallInt::kMaxValue / length); 3146 word new_length = length * count; 3147 if (new_length <= SmallStr::kMaxLength) { 3148 // SmallStr result 3149 for (word i = 0; i < new_length; i++) { 3150 buffer[i] = str.byteAt(i % length); 3151 } 3152 return SmallStr::fromBytes(View<byte>(buffer, new_length)); 3153 } 3154 // LargeStr result 3155 HandleScope scope(thread); 3156 LargeStr result(&scope, createLargeStr(new_length)); 3157 const byte* src; 3158 if (length <= SmallStr::kMaxLength) { 3159 // SmallStr original 3160 str.copyTo(buffer, length); 3161 src = buffer; 3162 } else { 3163 // LargeStr original 3164 LargeStr source(&scope, *str); 3165 src = reinterpret_cast<byte*>(source.address()); 3166 } 3167 byte* dst = reinterpret_cast<byte*>(result.address()); 3168 for (word i = 0; i < count; i++, dst += length) { 3169 std::memcpy(dst, src, length); 3170 } 3171 return *result; 3172} 3173 3174RawObject Runtime::strSlice(Thread* thread, const Str& str, word start, 3175 word stop, word step) { 3176 word length = Slice::length(start, stop, step); 3177 word start_index = str.offsetByCodePoints(0, start); 3178 3179 if (step == 1) { 3180 word end_index = str.offsetByCodePoints(start_index, length); 3181 word num_chars = end_index - start_index; 3182 return strSubstr(thread, str, start_index, num_chars); 3183 } 3184 3185 word result_length = 0; 3186 for (word i = 0, char_index = start_index; i < length; 3187 i++, char_index = str.offsetByCodePoints(char_index, step)) { 3188 result_length += UTF8::numChars(str.byteAt(char_index)); 3189 } 3190 3191 if (result_length <= SmallStr::kMaxLength) { 3192 byte buffer[SmallStr::kMaxLength]; 3193 for (word i = 0, char_index = start_index; i < result_length; 3194 char_index = str.offsetByCodePoints(char_index, step)) { 3195 word num_chars = UTF8::numChars(str.byteAt(char_index)); 3196 str.copyToStartAt(&buffer[i], num_chars, char_index); 3197 i += num_chars; 3198 } 3199 return SmallStr::fromBytes({buffer, result_length}); 3200 } 3201 3202 HandleScope scope(thread); 3203 MutableBytes result( 3204 &scope, thread->runtime()->newMutableBytesUninitialized(result_length)); 3205 for (word i = 0, char_index = start_index; i < result_length; 3206 char_index = str.offsetByCodePoints(char_index, step)) { 3207 word num_chars = UTF8::numChars(str.byteAt(char_index)); 3208 result.replaceFromWithStrStartAt(i, *str, num_chars, char_index); 3209 i += num_chars; 3210 } 3211 return result.becomeStr(); 3212} 3213 3214// StrArray 3215 3216void Runtime::strArrayAddASCII(Thread* thread, const StrArray& array, 3217 byte code_point) { 3218 DCHECK(code_point <= kMaxASCII, "can only add ASCII in strArrayAddASCII"); 3219 word num_items = array.numItems(); 3220 word new_length = num_items + 1; 3221 strArrayEnsureCapacity(thread, array, new_length); 3222 array.setNumItems(new_length); 3223 MutableBytes::cast(array.items()).byteAtPut(num_items, code_point); 3224} 3225 3226void Runtime::strArrayAddCodePoint(Thread* thread, const StrArray& array, 3227 int32_t code_point) { 3228 DCHECK_BOUND(code_point, kMaxUnicode); 3229 RawSmallStr str = SmallStr::fromCodePoint(code_point); 3230 word num_items = array.numItems(); 3231 word length = str.length(); 3232 word new_length = num_items + length; 3233 strArrayEnsureCapacity(thread, array, new_length); 3234 byte* dst = 3235 reinterpret_cast<byte*>(MutableBytes::cast(array.items()).address()); 3236 str.copyTo(dst + num_items, length); 3237 array.setNumItems(new_length); 3238} 3239 3240void Runtime::strArrayAddStr(Thread* thread, const StrArray& array, 3241 const Str& str) { 3242 word length = str.length(); 3243 if (length == 0) return; 3244 word num_items = array.numItems(); 3245 word new_length = length + num_items; 3246 strArrayEnsureCapacity(thread, array, new_length); 3247 byte* dst = 3248 reinterpret_cast<byte*>(MutableBytes::cast(array.items()).address()); 3249 str.copyTo(dst + num_items, length); 3250 array.setNumItems(new_length); 3251} 3252 3253void Runtime::strArrayAddStrArray(Thread* thread, const StrArray& array, 3254 const StrArray& str) { 3255 word length = str.numItems(); 3256 if (length == 0) return; 3257 word num_items = array.numItems(); 3258 word new_length = length + num_items; 3259 strArrayEnsureCapacity(thread, array, new_length); 3260 byte* dst = 3261 reinterpret_cast<byte*>(MutableBytes::cast(array.items()).address()); 3262 str.copyTo(dst + num_items, length); 3263 array.setNumItems(new_length); 3264} 3265 3266void Runtime::strArrayEnsureCapacity(Thread* thread, const StrArray& array, 3267 word min_capacity) { 3268 DCHECK_BOUND(min_capacity, SmallInt::kMaxValue); 3269 word curr_capacity = array.capacity(); 3270 if (min_capacity <= curr_capacity) return; 3271 word new_capacity = newCapacity(curr_capacity, min_capacity); 3272 HandleScope scope(thread); 3273 MutableBytes new_bytes(&scope, newMutableBytesZeroed(new_capacity)); 3274 new_bytes.replaceFromWith(0, MutableBytes::cast(array.items()), 3275 array.numItems()); 3276 array.setItems(*new_bytes); 3277} 3278 3279RawObject Runtime::newCell() { 3280 return newInstanceWithSize(LayoutId::kCell, Cell::kSize); 3281} 3282 3283RawObject Runtime::newClassMethod() { 3284 return newInstanceWithSize(LayoutId::kClassMethod, ClassMethod::kSize); 3285} 3286 3287RawObject Runtime::newSuper() { 3288 return newInstanceWithSize(LayoutId::kSuper, Super::kSize); 3289} 3290 3291RawObject Runtime::newStrIterator(const Object& str) { 3292 HandleScope scope(Thread::current()); 3293 StrIterator result( 3294 &scope, newInstanceWithSize(LayoutId::kStrIterator, StrIterator::kSize)); 3295 result.setIndex(0); 3296 result.setIterable(*str); 3297 return *result; 3298} 3299 3300RawObject Runtime::newTupleIterator(const Tuple& tuple, word length) { 3301 HandleScope scope(Thread::current()); 3302 TupleIterator result(&scope, newInstanceWithSize(LayoutId::kTupleIterator, 3303 TupleIterator::kSize)); 3304 result.setIndex(0); 3305 result.setIterable(*tuple); 3306 result.setLength(length); 3307 return *result; 3308} 3309 3310RawObject Runtime::newContext(const Dict& data) { 3311 HandleScope scope(Thread::current()); 3312 Context result(&scope, 3313 newInstanceWithSize(LayoutId::kContext, Context::kSize)); 3314 result.setData(*data); 3315 result.setPrevContext(NoneType::object()); 3316 return *result; 3317} 3318 3319RawObject Runtime::newContextVar(const Str& name, const Object& default_value) { 3320 HandleScope scope(Thread::current()); 3321 ContextVar result( 3322 &scope, newInstanceWithSize(LayoutId::kContextVar, ContextVar::kSize)); 3323 result.setName(*name); 3324 result.setDefaultValue(*default_value); 3325 return *result; 3326} 3327 3328RawObject Runtime::newToken(const Context& ctx, const ContextVar& var, 3329 const Object& old_value) { 3330 HandleScope scope(Thread::current()); 3331 Token result(&scope, newInstanceWithSize(LayoutId::kToken, Token::kSize)); 3332 result.setContext(*ctx); 3333 result.setVar(*var); 3334 result.setOldValue(*old_value); 3335 result.setUsed(false); 3336 return *result; 3337} 3338 3339RawObject Runtime::emptyFrozenSet() { return empty_frozen_set_; } 3340 3341RawObject Runtime::layoutNewAttribute(const Object& name, AttributeInfo info) { 3342 RawMutableTuple result = MutableTuple::cast(newMutableTuple(2)); 3343 result.atPut(0, *name); 3344 result.atPut(1, info.asSmallInt()); 3345 return result.becomeImmutable(); 3346} 3347 3348static RawObject layoutFollowEdge(RawObject edges, RawObject key) { 3349 RawList list = List::cast(edges); 3350 DCHECK(list.numItems() % 2 == 0, 3351 "edges must contain an even number of elements"); 3352 for (word i = 0, num_items = list.numItems(); i < num_items; i += 2) { 3353 if (list.at(i) == key) { 3354 return list.at(i + 1); 3355 } 3356 } 3357 return Error::notFound(); 3358} 3359 3360static void layoutAddEdge(Thread* thread, Runtime* runtime, const List& edges, 3361 const Object& key, const Object& layout) { 3362 DCHECK(edges.numItems() % 2 == 0, 3363 "edges must contain an even number of elements"); 3364 runtime->listAdd(thread, edges, key); 3365 runtime->listAdd(thread, edges, layout); 3366} 3367 3368bool Runtime::layoutFindAttribute(RawLayout layout, const Object& name, 3369 AttributeInfo* info) { 3370 // Check in-object attributes 3371 RawTuple in_object = Tuple::cast(layout.inObjectAttributes()); 3372 RawObject name_raw = *name; 3373 for (word i = in_object.length() - 1; i >= 0; i--) { 3374 RawTuple entry = Tuple::cast(in_object.at(i)); 3375 if (entry.at(0) == name_raw) { 3376 *info = AttributeInfo(entry.at(1)); 3377 return true; 3378 } 3379 } 3380 3381 // Check overflow attributes 3382 if (!layout.hasTupleOverflow()) { 3383 return false; 3384 } 3385 3386 RawTuple overflow = Tuple::cast(layout.overflowAttributes()); 3387 for (word i = overflow.length() - 1; i >= 0; i--) { 3388 RawTuple entry = Tuple::cast(overflow.at(i)); 3389 if (entry.at(0) == name_raw) { 3390 *info = AttributeInfo(entry.at(1)); 3391 return true; 3392 } 3393 } 3394 return false; 3395} 3396 3397RawObject Runtime::layoutCreateCopy(Thread* thread, const Layout& layout) { 3398 HandleScope scope(thread); 3399 LayoutId id = reserveLayoutId(thread); 3400 Layout new_layout(&scope, newLayout(id)); 3401 new_layout.setDescribedType(layout.describedType()); 3402 new_layout.setNumInObjectAttributes(layout.numInObjectAttributes()); 3403 new_layout.setInObjectAttributes(layout.inObjectAttributes()); 3404 new_layout.setOverflowAttributes(layout.overflowAttributes()); 3405 layoutAtPut(id, *new_layout); 3406 return *new_layout; 3407} 3408 3409RawObject Runtime::layoutAddAttributeEntry(Thread* thread, const Tuple& entries, 3410 const Object& name, 3411 AttributeInfo info) { 3412 HandleScope scope(thread); 3413 word entries_len = entries.length(); 3414 MutableTuple new_entries(&scope, newMutableTuple(entries_len + 1)); 3415 new_entries.replaceFromWith(0, *entries, entries_len); 3416 3417 new_entries.atPut(entries_len, layoutNewAttribute(name, info)); 3418 3419 return new_entries.becomeImmutable(); 3420} 3421 3422static RawUnbound kDictOverflowLayoutTransitionEdgeName = Unbound::object(); 3423 3424RawObject Runtime::typeDictOnlyLayout(Thread* thread, const Type& type, 3425 word num_in_object_attr) { 3426 HandleScope scope(thread); 3427 Layout type_instance_layout(&scope, type.instanceLayout()); 3428 // Find a layout derived from type, whose in-object attributes' length matches 3429 // the needed `num_in_object_attr`. 3430 List edges(&scope, type_instance_layout.deletions()); 3431 DCHECK(edges.numItems() % 2 == 0, 3432 "edges must contain an even number of elements"); 3433 // This name is used only for the internal layout transition edge from 3434 // a layout to a new one with dict overflow. 3435 Object key(&scope, kDictOverflowLayoutTransitionEdgeName); 3436 for (word i = 0, num_items = edges.numItems(); i < num_items; i += 2) { 3437 if (edges.at(i) == key) { 3438 if (Layout::cast(edges.at(i + 1)).numInObjectAttributes() == 3439 num_in_object_attr) { 3440 return edges.at(i + 1); 3441 } 3442 } 3443 } 3444 Layout new_layout(&scope, layoutCreateCopy(thread, type_instance_layout)); 3445 // This annotates `new_layout` to return it when requested next time. 3446 new_layout.setNumInObjectAttributes(num_in_object_attr); 3447 new_layout.setInObjectAttributes(emptyTuple()); 3448 new_layout.setOverflowAttributes(emptyTuple()); 3449 new_layout.setDictOverflowOffset(new_layout.overflowOffset()); 3450 // Add the edge to the existing layout. 3451 layoutAddEdge(thread, this, edges, key, new_layout); 3452 return *new_layout; 3453} 3454 3455RawObject Runtime::layoutAddAttribute(Thread* thread, const Layout& layout, 3456 const Object& name, word flags, 3457 AttributeInfo* info) { 3458 // Check if a edge for the attribute addition already exists 3459 RawObject result = layoutFollowEdge(layout.additions(), *name); 3460 if (!result.isError()) { 3461 bool found = layoutFindAttribute(Layout::cast(result), name, info); 3462 DCHECK(found, "couldn't find attribute on new layout"); 3463 return result; 3464 } 3465 3466 // Create a new layout and figure out where to place the attribute 3467 HandleScope scope(thread); 3468 Layout new_layout(&scope, layoutCreateCopy(thread, layout)); 3469 Tuple inobject(&scope, layout.inObjectAttributes()); 3470 if (inobject.length() < layout.numInObjectAttributes()) { 3471 *info = AttributeInfo(inobject.length() * kPointerSize, 3472 flags | AttributeFlags::kInObject); 3473 new_layout.setInObjectAttributes( 3474 layoutAddAttributeEntry(thread, inobject, name, *info)); 3475 } else { 3476 Tuple overflow(&scope, layout.overflowAttributes()); 3477 *info = AttributeInfo(overflow.length(), flags); 3478 new_layout.setOverflowAttributes( 3479 layoutAddAttributeEntry(thread, overflow, name, *info)); 3480 } 3481 3482 // Add the edge to the existing layout 3483 List edges(&scope, layout.additions()); 3484 layoutAddEdge(thread, this, edges, name, new_layout); 3485 3486 return *new_layout; 3487} 3488 3489RawObject Runtime::layoutSetDescribedType(Thread* thread, const Layout& from, 3490 const Type& to) { 3491 // Check if a edge for the attribute addition already exists 3492 HandleScope scope(thread); 3493 MutableTuple transitions(&scope, layout_type_transitions_); 3494 word length = transitions.length(); 3495 word first_free = length; 3496 for (word i = 0; i < length; i += LayoutTypeTransition::kTransitionSize) { 3497 RawObject found_from = transitions.at(i + LayoutTypeTransition::kFrom); 3498 if (found_from == from && 3499 transitions.at(i + LayoutTypeTransition::kTo) == to) { 3500 // The transition exists; return the result layout 3501 return transitions.at(i + LayoutTypeTransition::kResult); 3502 } 3503 if (first_free == length && found_from == SmallInt::fromWord(0)) { 3504 // There's an empty slot we can use to store the transition 3505 first_free = i; 3506 } 3507 } 3508 3509 // Make a new layout and transition the type 3510 Layout result(&scope, layoutCreateCopy(thread, from)); 3511 result.setDescribedType(*to); 3512 3513 // If needed, grow the table 3514 word index = first_free; 3515 word needed_length = index + LayoutTypeTransition::kTransitionSize; 3516 if (needed_length > length) { 3517 word new_length = newCapacity(length, /*min_capacity=*/needed_length); 3518 MutableTuple new_tuple(&scope, newMutableTuple(new_length)); 3519 new_tuple.replaceFromWith(0, *transitions, length); 3520 layout_type_transitions_ = *new_tuple; 3521 transitions = *new_tuple; 3522 } 3523 3524 // Add the edge to the layout 3525 transitions.atPut(index + LayoutTypeTransition::kFrom, *from); 3526 transitions.atPut(index + LayoutTypeTransition::kTo, *to); 3527 transitions.atPut(index + LayoutTypeTransition::kResult, *result); 3528 3529 return *result; 3530} 3531 3532static RawObject markEntryDeleted(Thread* thread, RawObject entries, 3533 const Object& name) { 3534 HandleScope scope(thread); 3535 Tuple entries_old(&scope, entries); 3536 word length = entries_old.length(); 3537 DCHECK(length > 0, "length must be positive"); 3538 Runtime* runtime = thread->runtime(); 3539 MutableTuple entries_new(&scope, runtime->newMutableTuple(length)); 3540 Object zero(&scope, SmallInt::fromWord(0)); 3541 Tuple entry(&scope, runtime->emptyTuple()); 3542 for (word i = 0; i < length; i++) { 3543 entry = entries_old.at(i); 3544 if (entry.at(0) == name) { 3545 AttributeInfo old_info(entry.at(1)); 3546 AttributeInfo info(old_info.offset(), AttributeFlags::kDeleted); 3547 entry = runtime->layoutNewAttribute(/*name=*/zero, info); 3548 } 3549 entries_new.atPut(i, *entry); 3550 } 3551 return entries_new.becomeImmutable(); 3552} 3553 3554RawObject Runtime::layoutDeleteAttribute(Thread* thread, const Layout& layout, 3555 const Object& name, 3556 AttributeInfo info) { 3557 // Check if an edge exists for removing the attribute 3558 RawObject next_layout = layoutFollowEdge(layout.deletions(), *name); 3559 if (!next_layout.isError()) { 3560 return next_layout; 3561 } 3562 3563 // No edge was found, create a new layout and add an edge 3564 HandleScope scope(thread); 3565 Layout new_layout(&scope, layoutCreateCopy(thread, layout)); 3566 if (info.isInObject()) { 3567 new_layout.setInObjectAttributes( 3568 markEntryDeleted(thread, layout.inObjectAttributes(), name)); 3569 } else { 3570 new_layout.setOverflowAttributes( 3571 markEntryDeleted(thread, layout.overflowAttributes(), name)); 3572 } 3573 3574 // Add the edge to the existing layout 3575 List edges(&scope, layout.deletions()); 3576 layoutAddEdge(thread, this, edges, name, new_layout); 3577 3578 return *new_layout; 3579} 3580 3581void Runtime::layoutSetTupleOverflow(RawLayout layout) { 3582 layout.setOverflowAttributes(emptyTuple()); 3583} 3584 3585void Runtime::clearHandleScopes() { 3586 MutexGuard lock(&threads_mutex_); 3587 for (Thread* thread = main_thread_; thread != nullptr; 3588 thread = thread->next()) { 3589 Handles* handles = thread->handles(); 3590 Object* handle = handles->head(); 3591 while (handle != nullptr) { 3592 handle = handle->nextHandle(); 3593 handles->pop(handle); 3594 } 3595 } 3596} 3597 3598void Runtime::freeApiHandles() { 3599 // Dealloc the Module handles first as they are the handle roots 3600 Thread* thread = Thread::current(); 3601 HandleScope scope(thread); 3602 Dict modules(&scope, modules_); 3603 // Clear the modules dict and run a GC, to run dealloc slots on any now-dead 3604 // NativeProxy objects. 3605 dictClear(thread, modules); 3606 3607 // Dealloc modules referenced by modules_by_index. 3608 freeExtensionModules(thread); 3609 3610 // Process any native instance that is only referenced through the NativeProxy 3611 for (;;) { 3612 word before = numExtensionObjects(this) + numApiHandles(this); 3613 collectGarbage(); 3614 word after = numExtensionObjects(this) + numApiHandles(this); 3615 word num_handles_collected = before - after; 3616 if (num_handles_collected == 0) { 3617 // Fixpoint: no change in tracking 3618 break; 3619 } 3620 } 3621 collectGarbage(); 3622 3623 // Finally, skip trying to cleanly deallocate the object. Just free the 3624 // memory without calling the deallocation functions. 3625 disposeApiHandles(this); 3626 disposeExtensionObjects(this); 3627} 3628 3629RawObject Runtime::bytesToInt(Thread* thread, const Bytes& bytes, 3630 endian endianness, bool is_signed) { 3631 word length = bytes.length(); 3632 DCHECK(length <= kMaxWord - kWordSize, "huge length will overflow"); 3633 if (length == 0) { 3634 return SmallInt::fromWord(0); 3635 } 3636 3637 // Positive numbers that end up having the highest bit of their highest digit 3638 // set need an extra zero digit. 3639 byte high_byte = bytes.byteAt(endianness == endian::big ? 0 : length - 1); 3640 bool high_bit = high_byte & (1 << (kBitsPerByte - 1)); 3641 bool extra_digit = high_bit && !is_signed && length % kWordSize == 0; 3642 word num_digits = (length + (kWordSize - 1)) / kWordSize + extra_digit; 3643 HandleScope scope(thread); 3644 LargeInt result(&scope, createLargeInt(num_digits)); 3645 3646 byte sign_extension = (is_signed && high_bit) ? kMaxByte : 0; 3647 if (endianness == endian::little && endian::native == endian::little) { 3648 result.copyFrom(*bytes, sign_extension); 3649 } else { 3650 for (word d = 0; d < num_digits; ++d) { 3651 uword digit = 0; 3652 for (int w = 0; w < kWordSize; ++w) { 3653 word idx = d * kWordSize + w; 3654 byte b; 3655 if (idx >= length) { 3656 b = sign_extension; 3657 } else { 3658 b = bytes.byteAt(endianness == endian::big ? length - idx - 1 : idx); 3659 } 3660 digit |= static_cast<uword>(b) << (w * kBitsPerByte); 3661 } 3662 result.digitAtPut(d, digit); 3663 } 3664 } 3665 return normalizeLargeInt(thread, result); 3666} 3667 3668RawObject Runtime::normalizeLargeInt(Thread* thread, 3669 const LargeInt& large_int) { 3670 word shrink_to_digits = large_int.numDigits(); 3671 for (word digit = large_int.digitAt(shrink_to_digits - 1), next_digit; 3672 shrink_to_digits > 1; --shrink_to_digits, digit = next_digit) { 3673 next_digit = large_int.digitAt(shrink_to_digits - 2); 3674 // break if we have neither a redundant sign-extension nor a redundnant 3675 // zero-extension. 3676 if ((digit != -1 || next_digit >= 0) && (digit != 0 || next_digit < 0)) { 3677 break; 3678 } 3679 } 3680 if (shrink_to_digits == 1 && SmallInt::isValid(large_int.digitAt(0))) { 3681 return SmallInt::fromWord(large_int.digitAt(0)); 3682 } 3683 if (shrink_to_digits == large_int.numDigits()) { 3684 return *large_int; 3685 } 3686 3687 // Shrink. Future Optimization: Shrink in-place instead of copying. 3688 HandleScope scope(thread); 3689 LargeInt result(&scope, createLargeInt(shrink_to_digits)); 3690 for (word i = 0; i < shrink_to_digits; ++i) { 3691 result.digitAtPut(i, large_int.digitAt(i)); 3692 } 3693 return *result; 3694} 3695 3696static uword addWithCarry(uword x, uword y, uword carry_in, uword* carry_out) { 3697 DCHECK(carry_in <= 1, "carry must be 0 or 1"); 3698 uword sum; 3699 uword carry0 = __builtin_add_overflow(x, y, &sum); 3700 uword carry1 = __builtin_add_overflow(sum, carry_in, &sum); 3701 *carry_out = carry0 | carry1; 3702 return sum; 3703} 3704 3705RawObject Runtime::intAdd(Thread* thread, const Int& left, const Int& right) { 3706 if (left.isSmallInt() && right.isSmallInt()) { 3707 // Take a shortcut because we know the result fits in a word. 3708 word left_digit = SmallInt::cast(*left).value(); 3709 word right_digit = SmallInt::cast(*right).value(); 3710 return newInt(left_digit + right_digit); 3711 } 3712 3713 HandleScope scope(thread); 3714 word left_digits = left.numDigits(); 3715 word right_digits = right.numDigits(); 3716 Int longer(&scope, left_digits > right_digits ? *left : *right); 3717 Int shorter(&scope, left_digits <= right_digits ? *left : *right); 3718 3719 word shorter_digits = shorter.numDigits(); 3720 word longer_digits = longer.numDigits(); 3721 word result_digits = longer_digits + 1; 3722 LargeInt result(&scope, createLargeInt(result_digits)); 3723 uword carry = 0; 3724 for (word i = 0; i < shorter_digits; i++) { 3725 uword sum = 3726 addWithCarry(longer.digitAt(i), shorter.digitAt(i), carry, &carry); 3727 result.digitAtPut(i, sum); 3728 } 3729 uword shorter_sign_extension = shorter.isNegative() ? kMaxUword : 0; 3730 for (word i = shorter_digits; i < longer_digits; i++) { 3731 uword sum = 3732 addWithCarry(longer.digitAt(i), shorter_sign_extension, carry, &carry); 3733 result.digitAtPut(i, sum); 3734 } 3735 uword longer_sign_extension = longer.isNegative() ? kMaxUword : 0; 3736 uword high_digit = longer_sign_extension + shorter_sign_extension + carry; 3737 result.digitAtPut(result_digits - 1, high_digit); 3738 return normalizeLargeInt(thread, result); 3739} 3740 3741RawObject Runtime::intBinaryAnd(Thread* thread, const Int& left, 3742 const Int& right) { 3743 word left_digits = left.numDigits(); 3744 word right_digits = right.numDigits(); 3745 if (left_digits == 1 && right_digits == 1) { 3746 return newInt(left.asWord() & right.asWord()); 3747 } 3748 3749 HandleScope scope(thread); 3750 Int longer(&scope, left_digits > right_digits ? *left : *right); 3751 Int shorter(&scope, left_digits <= right_digits ? *left : *right); 3752 3753 word num_digits = longer.numDigits(); 3754 LargeInt result(&scope, createLargeInt(num_digits)); 3755 for (word i = 0, e = shorter.numDigits(); i < e; ++i) { 3756 result.digitAtPut(i, longer.digitAt(i) & shorter.digitAt(i)); 3757 } 3758 if (shorter.isNegative()) { 3759 for (word i = shorter.numDigits(); i < num_digits; ++i) { 3760 result.digitAtPut(i, longer.digitAt(i)); 3761 } 3762 } else { 3763 for (word i = shorter.numDigits(); i < num_digits; ++i) { 3764 result.digitAtPut(i, 0); 3765 } 3766 } 3767 return normalizeLargeInt(thread, result); 3768} 3769 3770RawObject Runtime::intInvert(Thread* thread, const Int& value) { 3771 word num_digits = value.numDigits(); 3772 if (num_digits == 1) { 3773 word value_word = value.asWord(); 3774 return newInt(~value_word); 3775 } 3776 HandleScope scope(thread); 3777 LargeInt large_int(&scope, *value); 3778 LargeInt result(&scope, createLargeInt(num_digits)); 3779 for (word i = 0; i < num_digits; ++i) { 3780 uword digit = large_int.digitAt(i); 3781 result.digitAtPut(i, ~digit); 3782 } 3783 DCHECK(result.isValid(), "valid large integer"); 3784 return *result; 3785} 3786 3787RawObject Runtime::intNegate(Thread* thread, const Int& value) { 3788 word num_digits = value.numDigits(); 3789 if (num_digits == 1) { 3790 word value_word = value.asWord(); 3791 // Negating kMinWord results in a number with two digits. 3792 if (value_word == kMinWord) { 3793 const uword min_word[] = {static_cast<uword>(kMinWord), 0}; 3794 return newLargeIntWithDigits(min_word); 3795 } 3796 return newInt(-value_word); 3797 } 3798 3799 HandleScope scope(thread); 3800 LargeInt large_int(&scope, *value); 3801 3802 auto digits_zero = [&](word up_to_digit) { 3803 for (word i = 0; i < up_to_digit; i++) { 3804 if (large_int.digitAt(i) != 0) { 3805 return false; 3806 } 3807 } 3808 return true; 3809 }; 3810 3811 // The result of negating a number like `digits == {0, 0, ..., 0x800000.. }` 3812 // needs an extra digit. 3813 uword highest_digit = large_int.digitAt(num_digits - 1); 3814 if (highest_digit == static_cast<uword>(kMinWord) && 3815 digits_zero(num_digits - 1)) { 3816 LargeInt result(&scope, createLargeInt(num_digits + 1)); 3817 for (word i = 0; i < num_digits; i++) { 3818 result.digitAtPut(i, large_int.digitAt(i)); 3819 } 3820 result.digitAtPut(num_digits, 0); 3821 DCHECK(result.isValid(), "Invalid LargeInt"); 3822 return *result; 3823 } 3824 // The result of negating a number like `digits == {0, 0, ..., 0x800000.., 0}` 3825 // is one digit shorter. 3826 if (highest_digit == 0 && 3827 large_int.digitAt(num_digits - 2) == static_cast<uword>(kMinWord) && 3828 digits_zero(num_digits - 2)) { 3829 LargeInt result(&scope, createLargeInt(num_digits - 1)); 3830 for (word i = 0; i < num_digits - 1; i++) { 3831 result.digitAtPut(i, large_int.digitAt(i)); 3832 } 3833 DCHECK(result.isValid(), "Invalid LargeInt"); 3834 return *result; 3835 } 3836 3837 LargeInt result(&scope, createLargeInt(num_digits)); 3838 word carry = 1; 3839 for (word i = 0; i < num_digits; i++) { 3840 uword digit = large_int.digitAt(i); 3841 static_assert(sizeof(digit) == sizeof(long), "invalid builtin size"); 3842 carry = __builtin_uaddl_overflow(~digit, carry, &digit); 3843 result.digitAtPut(i, digit); 3844 } 3845 DCHECK(carry == 0, "Carry should be zero"); 3846 DCHECK(result.isValid(), "Invalid LargeInt"); 3847 return *result; 3848} 3849 3850// The division algorithm operates on half words. This is because to implement 3851// multiword division we require a doubleword division operation such as 3852// (`uint128_t / uint64_t -> uint128_t`). Such an operation does not exist on 3853// most architectures (x86_64 only has `uint128_t / uint64_t -> uint64_t`, 3854// aarch64 only `uint64_t / uint64_t -> uint64_t`). Instead we perform the 3855// algorithm on half words and use a `uint64_t / uint32_t -> uint64_t` division. 3856// This is easier and faster than trying to emulate a doubleword division. 3857typedef uint32_t halfuword; 3858static_assert(sizeof(halfuword) == sizeof(uword) / 2, "halfuword size"); 3859 3860const int kBitsPerHalfWord = kBitsPerByte * sizeof(halfuword); 3861 3862static void halvesInvert(halfuword* halves, word num_halves) { 3863 for (word i = 0; i < num_halves; i++) { 3864 halves[i] = ~halves[i]; 3865 } 3866} 3867 3868static void halvesNegate(halfuword* halves, word num_halves) { 3869 uword carry = 1; 3870 for (word i = 0; i < num_halves; i++) { 3871 halfuword half = uword{~halves[i]} + carry; 3872 halves[i] = half; 3873 carry &= (half == 0); 3874 } 3875} 3876 3877static halfuword halvesAdd(halfuword* dest, const halfuword* src, 3878 word num_halves) { 3879 halfuword carry = 0; 3880 for (word i = 0; i < num_halves; i++) { 3881 uword sum = uword{dest[i]} + src[i] + carry; 3882 dest[i] = static_cast<halfuword>(sum); 3883 carry = sum >> kBitsPerHalfWord; 3884 } 3885 return carry; 3886} 3887 3888static void halvesIncrement(halfuword* halves, word num_halves, 3889 bool overflow_ok) { 3890 for (word i = 0; i < num_halves; i++) { 3891 halfuword half = halves[i] + 1; 3892 halves[i] = half; 3893 // We are done if there was no overflow. 3894 if (half != 0) break; 3895 DCHECK(overflow_ok || i < num_halves - 1, "overflow"); 3896 } 3897} 3898 3899static void halvesFromIntMagnitude(halfuword* halves, const Int& number) { 3900 word num_digits = number.numDigits(); 3901 for (word i = 0; i < num_digits; i++) { 3902 uword digit = number.digitAt(i); 3903 halves[i * 2] = static_cast<halfuword>(digit); 3904 halves[i * 2 + 1] = digit >> kBitsPerHalfWord; 3905 } 3906 if (number.isNegative()) { 3907 halvesNegate(halves, num_digits * 2); 3908 } 3909} 3910 3911// Given an array of size `num_halves` checks how many items at the end of the 3912// array is zero and returns a reduced length without them. Put another way: 3913// It drops leading zeros from an arbitrary precision little endian number. 3914static word halvesNormalize(halfuword* halves, word num_halves) { 3915 while (halves[num_halves - 1] == 0) { 3916 num_halves--; 3917 DCHECK(num_halves > 0, "must not have every digit zero"); 3918 } 3919 return num_halves; 3920} 3921 3922static void halvesDecrement(halfuword* halves, word num_halves) { 3923 DCHECK(num_halves > 0, "must have at least one half"); 3924 for (word i = 0; i < num_halves; i++) { 3925 halfuword half = halves[i] - 1; 3926 halves[i] = half; 3927 // We are done if there is no borrow left. 3928 if (half != ~halfuword{0}) return; 3929 } 3930 // Must only be used in situations that cannot underflow. 3931 UNREACHABLE("underflow"); 3932} 3933 3934static void halvesShiftLeft(halfuword* halves, word num_halves, word shift) { 3935 DCHECK(shift < kBitsPerHalfWord, "must not shift more than a halfuword"); 3936 if (shift == 0) return; 3937 3938 halfuword prev = 0; 3939 for (word i = 0; i < num_halves; i++) { 3940 halfuword half = halves[i]; 3941 halves[i] = (half << shift) | (prev >> (kBitsPerHalfWord - shift)); 3942 prev = half; 3943 } 3944 DCHECK(prev >> (kBitsPerHalfWord - shift) == 0, "must not overflow"); 3945} 3946 3947static void halvesShiftRight(halfuword* halves, word num_halves, word shift) { 3948 DCHECK(shift < kBitsPerHalfWord, "must not shift more than a halfuword"); 3949 if (shift == 0) return; 3950 3951 halfuword prev = 0; 3952 for (word i = num_halves - 1; i >= 0; i--) { 3953 halfuword half = halves[i]; 3954 halves[i] = (half >> shift) | (prev << (kBitsPerHalfWord - shift)); 3955 prev = half; 3956 } 3957} 3958 3959static RawObject largeIntFromHalves(Thread* thread, const halfuword* halves, 3960 word num_halves) { 3961 DCHECK(num_halves % 2 == 0, "must have even number of halves"); 3962 word digits = num_halves / 2; 3963 HandleScope scope(thread); 3964 Runtime* runtime = thread->runtime(); 3965 LargeInt result(&scope, runtime->createLargeInt(digits)); 3966 for (word i = 0; i < digits; i++) { 3967 uword digit = 3968 halves[i * 2] | (uword{halves[i * 2 + 1]} << kBitsPerHalfWord); 3969 result.digitAtPut(i, digit); 3970 } 3971 return runtime->normalizeLargeInt(thread, result); 3972} 3973 3974// Compute quotient and modulo of dividing a large integer through a divisor 3975// whose magnitude fits in a `halfuword`. 3976static void divideModuloSingleHalfDivisor(Thread* thread, const Int& dividend, 3977 word divisor, Object* quotient, 3978 Object* modulo) { 3979 DCHECK(divisor >= 0 ? static_cast<halfuword>(divisor) == divisor 3980 : static_cast<halfuword>(-divisor) == -divisor, 3981 "divisor magnitude fits in half word"); 3982 3983 word dividend_digits = dividend.numDigits(); 3984 bool same_sign = dividend.isNegative() == (divisor < 0); 3985 halfuword divisor_half = divisor < 0 ? -divisor : divisor; 3986 uword result_halves = dividend_digits * 2; 3987 std::unique_ptr<halfuword[]> result(new halfuword[result_halves]); 3988 halvesFromIntMagnitude(result.get(), dividend); 3989 if (!same_sign) { 3990 halvesDecrement(result.get(), result_halves); 3991 } 3992 word significant_result_halves = halvesNormalize(result.get(), result_halves); 3993 3994 halfuword remainder = 0; 3995 for (word i = significant_result_halves - 1; i >= 0; i--) { 3996 uword digit = (uword{remainder} << kBitsPerHalfWord) | result[i]; 3997 result[i] = digit / divisor_half; 3998 remainder = digit % divisor_half; 3999 // Note that the division result fits into a halfuword, because the upper 4000 // half is the remainder from last round and therefore smaller than 4001 // `divisor_half`. 4002 } 4003 4004 Runtime* runtime = thread->runtime(); 4005 if (quotient) { 4006 if (!same_sign) { 4007 // Compute `-1 - quotient == -1 + (~quotient + 1) == ~quotient`. 4008 halvesInvert(result.get(), result_halves); 4009 } 4010 4011 *quotient = largeIntFromHalves(thread, result.get(), result_halves); 4012 } 4013 if (modulo) { 4014 word modulo_word; 4015 if (same_sign) { 4016 modulo_word = remainder; 4017 } else { 4018 modulo_word = -static_cast<word>(remainder) + divisor_half - 1; 4019 } 4020 if (divisor < 0) { 4021 modulo_word = -modulo_word; 4022 } 4023 *modulo = runtime->newInt(modulo_word); 4024 } 4025} 4026 4027// Perform unsigned integer division with multi-half dividend and divisor. 4028static void unsignedDivideRemainder(halfuword* result, word result_halves, 4029 halfuword* dividend, 4030 const halfuword* divisor, 4031 word divisor_halves) { 4032 // See Hackers Delight 9-2 "Multiword Division" and Knuth TAOCP volume 2, 4033 // 4.3.1 for this algorithm. 4034 DCHECK(divisor_halves > 1, "need at least 2 divisor halves"); 4035 // Expects the divisor to be normalized by left shifting until the highest bit 4036 // is set. This ensures that the guess performed in each iteration step is off 4037 // by no more than 2 (see Knuth for details and a proof). 4038 DCHECK((divisor[divisor_halves - 1] & (1 << (kBitsPerHalfWord - 1))) != 0, 4039 "need normalized divisor"); 4040 4041 // Performs some arithmetic with no more than half the bits of a `uword`. 4042 const uword half_mask = (uword{1} << kBitsPerHalfWord) - 1; 4043 4044 for (word r = result_halves - 1; r >= 0; r--) { 4045 // Take the two highest words of the dividend. We implicitly have 4046 // `dividend_halves = result_halves + divisor_halves - 1` (the actual 4047 // dividend array is guaranteed to have at least one more half filled with 4048 // zero on top for the first round). Since the dividend shrinks by 1 half 4049 // each round, the two highest digits can be found starting at 4050 // `r + divisor_halves - 1`. 4051 uword dividend_high_word = 4052 (uword{dividend[r + divisor_halves]} << kBitsPerHalfWord) | 4053 uword{dividend[r + divisor_halves - 1]}; 4054 uword divisor_half = divisor[divisor_halves - 1]; 4055 4056 // Guess this result half by dividing the two highest dividend halves. 4057 // The guess gets us close: `guess_quot - 2 <= quot <= guess_quot`. 4058 uword guess_quot = dividend_high_word / divisor_half; 4059 uword guess_remainder = dividend_high_word % divisor_half; 4060 4061 // Iterate until the guess is exact. 4062 while (guess_quot > half_mask || 4063 guess_quot * divisor[divisor_halves - 2] > 4064 ((guess_remainder << kBitsPerHalfWord) | 4065 dividend[r + divisor_halves - 2])) { 4066 guess_quot--; 4067 guess_remainder += divisor_half; 4068 if (guess_remainder > half_mask) break; 4069 } 4070 4071 // Multiply and subtract from dividend. 4072 uword borrow = 0; 4073 for (word d = 0; d < divisor_halves; d++) { 4074 uword product = guess_quot * divisor[d]; 4075 word diff = 4076 static_cast<word>(dividend[d + r]) - borrow - (product & half_mask); 4077 dividend[d + r] = static_cast<halfuword>(diff); 4078 borrow = (product >> kBitsPerHalfWord) - (diff >> kBitsPerHalfWord); 4079 } 4080 word diff = static_cast<word>(dividend[r + divisor_halves]) - borrow; 4081 dividend[r + divisor_halves] = static_cast<halfuword>(diff); 4082 4083 // If we subtracted too much, add back. 4084 if (diff < 0) { 4085 guess_quot--; 4086 halfuword carry = halvesAdd(&dividend[r], divisor, divisor_halves); 4087 dividend[r + divisor_halves] += carry; 4088 } 4089 4090 result[r] = guess_quot; 4091 } 4092} 4093 4094// Like Runtime::intDivideModulo() but specifically for the case of the 4095// divisor's magnitued being bigger than the dividend's. 4096static void divideWithBiggerDivisor(Thread* thread, const Int& dividend, 4097 const Int& divisor, Object* quotient, 4098 Object* modulo) { 4099 if (dividend.isZero()) { 4100 if (quotient != nullptr) *quotient = SmallInt::fromWord(0); 4101 if (modulo != nullptr) *modulo = SmallInt::fromWord(0); 4102 return; 4103 } 4104 bool same_sign = dividend.isNegative() == divisor.isNegative(); 4105 if (quotient != nullptr) { 4106 *quotient = SmallInt::fromWord(same_sign ? 0 : -1); 4107 } 4108 if (modulo != nullptr) { 4109 if (!same_sign) { 4110 *modulo = thread->runtime()->intAdd(thread, divisor, dividend); 4111 } else if (dividend.isBool()) { 4112 *modulo = convertBoolToInt(*dividend); 4113 } else { 4114 *modulo = *dividend; 4115 } 4116 } 4117} 4118 4119bool Runtime::intDivideModulo(Thread* thread, const Int& dividend, 4120 const Int& divisor, Object* quotient, 4121 Object* modulo) { 4122 // Some notes for understanding this code: 4123 // - This is built around an unsigned division algorithm in 4124 // `unsignedDivideRemainder()`. 4125 // - Remember that this implements floor div and modulo which is different 4126 // from C++ giving you truncated div and remainder when operands are 4127 // negative. 4128 // - To build a signed floor division from an unsigned division primitive we 4129 // use the following formula when the sign of dividend and divisor differs: 4130 // floor_div = -1 - (abs(dividend) - 1) / abs(divisor) 4131 // modulo = divisor_sign * 4132 // (abs(divisor) - 1 - (abs(dividend) - 1) % abs(divisor)) 4133 4134 // TODO(matthiasb): Optimization idea: Fuse the independent operations/loops 4135 // on arrays of `halfuword`s to reduce the number of passes over the data. 4136 4137 word divisor_digits = divisor.numDigits(); 4138 word dividend_digits = dividend.numDigits(); 4139 bool same_sign = dividend.isNegative() == divisor.isNegative(); 4140 if (divisor_digits == 1) { 4141 word divisor_word = divisor.asWord(); 4142 if (divisor_word == 0) { 4143 return false; 4144 } 4145 // Handle -1 as a special case because for dividend being the smallest 4146 // negative number possible for the amount of digits and `divisor == -1` 4147 // produces a result that is bigger than the input. 4148 if (divisor_word == -1) { 4149 if (quotient != nullptr) *quotient = intNegate(thread, dividend); 4150 if (modulo != nullptr) *modulo = SmallInt::fromWord(0); 4151 return true; 4152 } 4153 if (dividend_digits == 1) { 4154 word dividend_word = dividend.asWord(); 4155 word quotient_word = dividend_word / divisor_word; 4156 word modulo_word = dividend_word % divisor_word; 4157 if (!same_sign && modulo_word) { 4158 DCHECK(quotient_word > kMinWord, "underflow"); 4159 quotient_word--; 4160 modulo_word += divisor_word; 4161 } 4162 if (quotient != nullptr) *quotient = newInt(quotient_word); 4163 if (modulo != nullptr) *modulo = newInt(modulo_word); 4164 return true; 4165 } 4166 4167 // Handle the case where `abs(divisor)` fits in single half word. 4168 // This helps performance and simplifies `unsignedDivideRemainder()` because 4169 // it can assume to have at least 2 divisor half words. 4170 word max_half_uword = (word{1} << kBitsPerHalfWord) - 1; 4171 if (-max_half_uword <= divisor_word && divisor_word <= max_half_uword) { 4172 divideModuloSingleHalfDivisor(thread, dividend, divisor_word, quotient, 4173 modulo); 4174 return true; 4175 } 4176 } 4177 4178 if (divisor_digits > dividend_digits) { 4179 divideWithBiggerDivisor(thread, dividend, divisor, quotient, modulo); 4180 return true; 4181 } 4182 4183 // Convert divisor to `halfuword`s. Normalize by left shifting until the 4184 // highest bit (of the highest half) is set as required by 4185 // `unsignedDivideRemainder()`. We count the non-zero halves in the 4186 // `significant_xxx_halves` variables. 4187 word divisor_halves = divisor_digits * 2; 4188 std::unique_ptr<halfuword[]> divisor_n(new halfuword[divisor_halves]); 4189 halvesFromIntMagnitude(divisor_n.get(), divisor); 4190 word significant_divisor_halves = 4191 halvesNormalize(divisor_n.get(), divisor_halves); 4192 static_assert(sizeof(divisor_n[0]) == sizeof(unsigned), 4193 "choose right builtin"); 4194 int shift = __builtin_clz(divisor_n[significant_divisor_halves - 1]); 4195 halvesShiftLeft(divisor_n.get(), significant_divisor_halves, shift); 4196 4197 // Convert dividend to `halfuword`s and shift by the same amount we used for 4198 // the divisor. We reserve 1 extra half so we can save a bounds check in 4199 // `unsignedDivideRemainder()` because `dividend_halves` will still be valid 4200 // to access at index `significant_divisor_halves`. 4201 word dividend_halves = (dividend_digits + 1) * 2; 4202 std::unique_ptr<halfuword[]> dividend_n(new halfuword[dividend_halves]); 4203 halvesFromIntMagnitude(dividend_n.get(), dividend); 4204 dividend_n[dividend_halves - 1] = 0; 4205 dividend_n[dividend_halves - 2] = 0; 4206 if (!same_sign) { 4207 halvesDecrement(dividend_n.get(), dividend_halves); 4208 } 4209 halvesShiftLeft(dividend_n.get(), dividend_halves, shift); 4210 word significant_dividend_halves = 4211 halvesNormalize(dividend_n.get(), dividend_halves); 4212 4213 // Handle special case of divisor being bigger than the dividend. 4214 if (significant_divisor_halves > significant_dividend_halves || 4215 (significant_divisor_halves == significant_dividend_halves && 4216 divisor_n[significant_divisor_halves - 1] > 4217 dividend_n[significant_divisor_halves - 1])) { 4218 divideWithBiggerDivisor(thread, dividend, divisor, quotient, modulo); 4219 return true; 4220 } 4221 4222 // Allocate storage for result. Make sure we have an even number of halves. 4223 word result_halves = (dividend_halves - divisor_halves + 2) & ~1; 4224 DCHECK(result_halves % 2 == 0, "even number of halves"); 4225 std::unique_ptr<halfuword[]> result(new halfuword[result_halves]); 4226 word significant_result_halves = 4227 significant_dividend_halves - significant_divisor_halves + 1; 4228 DCHECK(significant_result_halves <= result_halves, "no overflow"); 4229 4230 unsignedDivideRemainder(result.get(), significant_result_halves, 4231 dividend_n.get(), divisor_n.get(), 4232 significant_divisor_halves); 4233 4234 // TODO(matthiasb): We copy the data in result[] to a new LargeInt, 4235 // normalizeLargeInt will probably just copy it again. Should we normalize on 4236 // result[]? Can we do it without duplicating the normalization code? 4237 4238 if (quotient != nullptr) { 4239 for (word i = significant_result_halves; i < result_halves; i++) { 4240 result[i] = 0; 4241 } 4242 if (!same_sign) { 4243 // Compute `-1 - quotient == -1 + (~quotient + 1) == ~quotient`. 4244 halvesInvert(result.get(), result_halves); 4245 } 4246 4247 *quotient = largeIntFromHalves(thread, result.get(), result_halves); 4248 } 4249 if (modulo != nullptr) { 4250 // `dividend` contains the remainder now. First revert normalization shift. 4251 halvesShiftRight(dividend_n.get(), significant_dividend_halves, shift); 4252 if (!same_sign) { 4253 // Revert divisor shift. 4254 halvesShiftRight(divisor_n.get(), significant_divisor_halves, shift); 4255 // Compute `-remainder + divisor - 1`. 4256 halvesNegate(dividend_n.get(), dividend_halves); 4257 halfuword carry = halvesAdd(dividend_n.get(), divisor_n.get(), 4258 significant_divisor_halves); 4259 DCHECK(carry <= 1, "carry <= 1"); 4260 if (carry) { 4261 halvesIncrement(dividend_n.get() + significant_divisor_halves, 4262 dividend_halves - significant_divisor_halves, true); 4263 } 4264 4265 halvesDecrement(dividend_n.get(), dividend_halves); 4266 } 4267 if (divisor.isNegative()) { 4268 halvesNegate(dividend_n.get(), dividend_halves); 4269 } 4270 4271 *modulo = largeIntFromHalves(thread, dividend_n.get(), dividend_halves); 4272 } 4273 4274 return true; 4275} 4276 4277static uword subtractWithBorrow(uword x, uword y, uword borrow_in, 4278 uword* borrow_out) { 4279 DCHECK(borrow_in <= 1, "borrow must be 0 or 1"); 4280 uword difference; 4281 uword borrow0 = __builtin_sub_overflow(x, y, &difference); 4282 uword borrow1 = __builtin_sub_overflow(difference, borrow_in, &difference); 4283 *borrow_out = borrow0 | borrow1; 4284 return difference; 4285} 4286 4287static void fullMultiply(uword x, uword y, uword* result_low, 4288 uword* result_high) { 4289 static_assert(sizeof(uword) == 8, "assuming uword is 64bit"); 4290 auto result = __extension__ static_cast<unsigned __int128>(x) * y; 4291 *result_low = static_cast<uword>(result); 4292 *result_high = static_cast<uword>(result >> 64); 4293} 4294 4295RawObject Runtime::intMultiply(Thread* thread, const Int& left, 4296 const Int& right) { 4297 // See also Hackers Delight Chapter 8 Multiplication. 4298 word left_digits = left.numDigits(); 4299 word right_digits = right.numDigits(); 4300 if (left_digits == 1 && right_digits == 1) { 4301 word left_digit = static_cast<word>(left.digitAt(0)); 4302 word right_digit = static_cast<word>(right.digitAt(0)); 4303 word result; 4304 if (!__builtin_mul_overflow(left_digit, right_digit, &result)) { 4305 return newInt(result); 4306 } 4307 } 4308 4309 HandleScope scope(thread); 4310 word result_digits = left.numDigits() + right.numDigits(); 4311 LargeInt result(&scope, createLargeInt(result_digits)); 4312 4313 for (word i = 0; i < result_digits; i++) { 4314 result.digitAtPut(i, 0); 4315 } 4316 4317 // Perform an unsigned multiplication. 4318 for (word l = 0; l < left_digits; l++) { 4319 uword digit_left = left.digitAt(l); 4320 uword carry = 0; 4321 for (word r = 0; r < right_digits; r++) { 4322 uword digit_right = right.digitAt(r); 4323 uword result_digit = result.digitAt(l + r); 4324 4325 uword product_low; 4326 uword product_high; 4327 fullMultiply(digit_left, digit_right, &product_low, &product_high); 4328 uword carry0; 4329 uword sum0 = addWithCarry(result_digit, product_low, 0, &carry0); 4330 uword carry1; 4331 uword sum1 = addWithCarry(sum0, carry, 0, &carry1); 4332 result.digitAtPut(l + r, sum1); 4333 // Note that this cannot overflow: Even with digit_left and digit_right 4334 // being kMaxUword the result is something like 0xfff...e0000...1, so 4335 // carry1 will be zero in these cases where the high word is close to 4336 // overflow. 4337 carry = product_high + carry0 + carry1; 4338 } 4339 result.digitAtPut(l + right_digits, carry); 4340 } 4341 4342 // Correct for `left` signedness: 4343 // Interpreting a negative number as unsigned means we are off by 4344 // `2**num_bits` (i.e. for a single byte `-3 = 0b11111101` gets interpreted 4345 // as 253, which is off by `256 = 253 - -3 = 2**8`). 4346 // Hence if we interpreted a negative `left` as unsigned, the multiplication 4347 // result will be off by `right * 2**left_num_bits`. We can correct that by 4348 // subtracting `right << left_num_bits`. 4349 if (left.isNegative()) { 4350 uword borrow = 0; 4351 for (word r = 0; r < right_digits; r++) { 4352 uword right_digit = right.digitAt(r); 4353 uword result_digit = result.digitAt(r + left_digits); 4354 uword difference = 4355 subtractWithBorrow(result_digit, right_digit, borrow, &borrow); 4356 result.digitAtPut(r + left_digits, difference); 4357 } 4358 } 4359 // Correct for `right` signedness, analogous to the `left` correction. 4360 if (right.isNegative()) { 4361 uword borrow = 0; 4362 for (word l = 0; l < left_digits; l++) { 4363 uword left_digit = left.digitAt(l); 4364 uword result_digit = result.digitAt(l + right_digits); 4365 uword difference = 4366 subtractWithBorrow(result_digit, left_digit, borrow, &borrow); 4367 result.digitAtPut(l + right_digits, difference); 4368 } 4369 } 4370 4371 return normalizeLargeInt(thread, result); 4372} 4373 4374RawObject Runtime::intBinaryOr(Thread* thread, const Int& left, 4375 const Int& right) { 4376 word left_digits = left.numDigits(); 4377 word right_digits = right.numDigits(); 4378 if (left_digits == 1 && right_digits == 1) { 4379 return newInt(left.asWord() | right.asWord()); 4380 } 4381 4382 HandleScope scope(thread); 4383 Int longer(&scope, left_digits > right_digits ? *left : *right); 4384 Int shorter(&scope, left_digits <= right_digits ? *left : *right); 4385 word num_digits = longer.numDigits(); 4386 LargeInt result(&scope, createLargeInt(num_digits)); 4387 for (word i = 0, e = shorter.numDigits(); i < e; ++i) { 4388 result.digitAtPut(i, longer.digitAt(i) | shorter.digitAt(i)); 4389 } 4390 if (shorter.isNegative()) { 4391 for (word i = shorter.numDigits(); i < num_digits; ++i) { 4392 result.digitAtPut(i, kMaxUword); 4393 } 4394 } else { 4395 for (word i = shorter.numDigits(); i < num_digits; ++i) { 4396 result.digitAtPut(i, longer.digitAt(i)); 4397 } 4398 } 4399 return normalizeLargeInt(thread, result); 4400} 4401 4402RawObject Runtime::intBinaryRshift(Thread* thread, const Int& num, 4403 const Int& amount) { 4404 DCHECK(!amount.isNegative(), "shift amount must be positive"); 4405 if (num.numDigits() == 1) { 4406 if (amount.numDigits() > 1) { 4407 return SmallInt::fromWord(0); 4408 } 4409 word amount_word = amount.asWord(); 4410 if (amount_word >= kBitsPerWord) { 4411 return SmallInt::fromWord(0); 4412 } 4413 word num_word = num.asWord(); 4414 return newInt(num_word >> amount_word); 4415 } 4416 4417 word amount_digits = amount.numDigits(); 4418 uword digit0 = amount.digitAt(0); 4419 word shift_words = digit0 / kBitsPerWord; 4420 word shift_bits = digit0 % kBitsPerWord; 4421 if (amount_digits > 1) { 4422 // It is impossible to create a LargeInt so big that a two-digit amount 4423 // would result in a non-zero result. 4424 if (amount_digits > 2) { 4425 return SmallInt::fromWord(0); 4426 } 4427 uword digit1 = amount.digitAt(1); 4428 // Must fit in a word and be positive. 4429 if (digit1 / kBitsPerWord / 2 != 0) { 4430 return SmallInt::fromWord(0); 4431 } 4432 shift_words |= digit1 * (kMaxUword / kBitsPerWord + 1); 4433 } 4434 4435 word result_digits = num.numDigits() - shift_words; 4436 if (result_digits < 0) { 4437 return SmallInt::fromWord(0); 4438 } 4439 if (shift_bits == 0 && shift_words == 0) { 4440 return *num; 4441 } 4442 HandleScope scope(thread); 4443 LargeInt result(&scope, createLargeInt(result_digits)); 4444 if (shift_bits == 0) { 4445 for (word i = 0; i < result_digits; i++) { 4446 result.digitAtPut(i, num.digitAt(shift_words + i)); 4447 } 4448 } else { 4449 uword prev = num.isNegative() ? kMaxUword : 0; 4450 word prev_shift = kBitsPerWord - shift_bits; 4451 for (word i = result_digits - 1; i >= 0; i--) { 4452 uword digit = num.digitAt(shift_words + i); 4453 uword result_digit = prev << prev_shift | digit >> shift_bits; 4454 result.digitAtPut(i, result_digit); 4455 prev = digit; 4456 } 4457 } 4458 return normalizeLargeInt(thread, result); 4459} 4460 4461RawObject Runtime::intBinaryLshift(Thread* thread, const Int& num, 4462 const Int& amount) { 4463 DCHECK(!amount.isNegative(), "shift amount must be non-negative"); 4464 4465 word num_digits = num.numDigits(); 4466 if (num_digits == 1 && num.asWord() == 0) return SmallInt::fromWord(0); 4467 CHECK(amount.numDigits() == 1, "lshift result is too large"); 4468 4469 word amount_word = amount.asWord(); 4470 if (amount_word == 0) { 4471 if (num.isBool()) { 4472 return convertBoolToInt(*num); 4473 } 4474 return *num; 4475 } 4476 4477 word shift_bits = amount_word % kBitsPerWord; 4478 word shift_words = amount_word / kBitsPerWord; 4479 word high_digit = num.digitAt(num.numDigits() - 1); 4480 4481 // check if high digit overflows when shifted - if we need an extra digit 4482 word bit_length = 4483 Utils::highestBit(high_digit >= 0 ? high_digit : ~high_digit); 4484 bool overflow = bit_length + shift_bits >= kBitsPerWord; 4485 4486 // check if result fits into one word 4487 word result_digits = num_digits + shift_words + overflow; 4488 if (result_digits == 1) { 4489 return newInt(high_digit << shift_bits); 4490 } 4491 4492 // allocate large int and zero-initialize low digits 4493 HandleScope scope(thread); 4494 LargeInt result(&scope, createLargeInt(result_digits)); 4495 for (word i = 0; i < shift_words; i++) { 4496 result.digitAtPut(i, 0); 4497 } 4498 4499 // iterate over digits of num and handle carrying 4500 if (shift_bits == 0) { 4501 for (word i = 0; i < num_digits; i++) { 4502 result.digitAtPut(i + shift_words, num.digitAt(i)); 4503 } 4504 DCHECK(!overflow, "overflow must be false with shift_bits==0"); 4505 } else { 4506 word right_shift = kBitsPerWord - shift_bits; 4507 uword prev = 0; 4508 for (word i = 0; i < num_digits; i++) { 4509 uword digit = num.digitAt(i); 4510 uword result_digit = (digit << shift_bits) | (prev >> right_shift); 4511 result.digitAtPut(i + shift_words, result_digit); 4512 prev = digit; 4513 } 4514 if (overflow) { 4515 // signed shift takes cares of keeping the sign 4516 word overflow_digit = static_cast<word>(prev) >> right_shift; 4517 result.digitAtPut(result_digits - 1, static_cast<uword>(overflow_digit)); 4518 } 4519 } 4520 DCHECK(result.isValid(), "result must be valid"); 4521 return *result; 4522} 4523 4524RawObject Runtime::intBinaryXor(Thread* thread, const Int& left, 4525 const Int& right) { 4526 word left_digits = left.numDigits(); 4527 word right_digits = right.numDigits(); 4528 if (left_digits == 1 && right_digits == 1) { 4529 return newInt(left.asWord() ^ right.asWord()); 4530 } 4531 4532 HandleScope scope(thread); 4533 Int longer(&scope, left_digits > right_digits ? *left : *right); 4534 Int shorter(&scope, left_digits <= right_digits ? *left : *right); 4535 4536 word num_digits = longer.numDigits(); 4537 LargeInt result(&scope, createLargeInt(num_digits)); 4538 for (word i = 0, e = shorter.numDigits(); i < e; ++i) { 4539 result.digitAtPut(i, longer.digitAt(i) ^ shorter.digitAt(i)); 4540 } 4541 if (shorter.isNegative()) { 4542 for (word i = shorter.numDigits(); i < num_digits; ++i) { 4543 result.digitAtPut(i, ~longer.digitAt(i)); 4544 } 4545 } else { 4546 for (word i = shorter.numDigits(); i < num_digits; ++i) { 4547 result.digitAtPut(i, longer.digitAt(i)); 4548 } 4549 } 4550 return normalizeLargeInt(thread, result); 4551} 4552 4553RawObject Runtime::intSubtract(Thread* thread, const Int& left, 4554 const Int& right) { 4555 if (left.isSmallInt() && right.isSmallInt()) { 4556 // Take a shortcut because we know the result fits in a word. 4557 word left_digit = SmallInt::cast(*left).value(); 4558 word right_digit = SmallInt::cast(*right).value(); 4559 return newInt(left_digit - right_digit); 4560 } 4561 4562 HandleScope scope(thread); 4563 word left_digits = left.numDigits(); 4564 word right_digits = right.numDigits(); 4565 4566 word shorter_digits = Utils::minimum(left_digits, right_digits); 4567 word longer_digits = Utils::maximum(left_digits, right_digits); 4568 word result_digits = longer_digits + 1; 4569 LargeInt result(&scope, createLargeInt(result_digits)); 4570 uword borrow = 0; 4571 for (word i = 0; i < shorter_digits; i++) { 4572 uword difference = 4573 subtractWithBorrow(left.digitAt(i), right.digitAt(i), borrow, &borrow); 4574 result.digitAtPut(i, difference); 4575 } 4576 uword left_sign_extension = left.isNegative() ? kMaxUword : 0; 4577 uword right_sign_extension = right.isNegative() ? kMaxUword : 0; 4578 if (right_digits == longer_digits) { 4579 for (word i = shorter_digits; i < longer_digits; i++) { 4580 uword difference = subtractWithBorrow(left_sign_extension, 4581 right.digitAt(i), borrow, &borrow); 4582 result.digitAtPut(i, difference); 4583 } 4584 } else { 4585 for (word i = shorter_digits; i < longer_digits; i++) { 4586 uword difference = subtractWithBorrow( 4587 left.digitAt(i), right_sign_extension, borrow, &borrow); 4588 result.digitAtPut(i, difference); 4589 } 4590 } 4591 uword high_digit = left_sign_extension - right_sign_extension - borrow; 4592 result.digitAtPut(result_digits - 1, high_digit); 4593 return normalizeLargeInt(thread, result); 4594} 4595 4596RawObject Runtime::intToBytes(Thread* thread, const Int& num, word length, 4597 endian endianness) { 4598 HandleScope scope(thread); 4599 Object result(&scope, Unbound::object()); 4600 byte buffer[SmallBytes::kMaxLength]; 4601 byte* dst; 4602 if (length <= SmallBytes::kMaxLength) { 4603 dst = buffer; 4604 } else { 4605 result = thread->runtime()->createLargeBytes(length); 4606 dst = reinterpret_cast<byte*>(LargeBytes::cast(*result).address()); 4607 } 4608 word extension_idx; 4609 word extension_length; 4610 if (endianness == endian::little && endian::native == endian::little) { 4611 word copied = num.copyTo(dst, length); 4612 extension_idx = copied; 4613 extension_length = length - copied; 4614 } else { 4615 word num_digits = num.numDigits(); 4616 for (word i = 0; i < num_digits; ++i) { 4617 uword digit = num.digitAt(i); 4618 for (int x = 0; x < kWordSize; ++x) { 4619 word idx = i * kWordSize + x; 4620 byte b = digit & kMaxByte; 4621 // The last digit may have more (insignificant) bits than the 4622 // resulting buffer. 4623 if (idx >= length) { 4624 return length <= SmallBytes::kMaxLength 4625 ? SmallBytes::fromBytes({buffer, length}) 4626 : *result; 4627 } 4628 if (endianness == endian::big) { 4629 idx = length - idx - 1; 4630 } 4631 dst[idx] = b; 4632 digit >>= kBitsPerByte; 4633 } 4634 } 4635 word num_bytes = num_digits * kWordSize; 4636 extension_idx = endianness == endian::big ? 0 : num_bytes; 4637 extension_length = length - num_bytes; 4638 } 4639 if (extension_length > 0) { 4640 byte sign_extension = num.isNegative() ? 0xff : 0; 4641 for (word i = 0; i < extension_length; ++i) { 4642 dst[extension_idx + i] = sign_extension; 4643 } 4644 } 4645 return length <= SmallBytes::kMaxLength 4646 ? SmallBytes::fromBytes({buffer, length}) 4647 : *result; 4648} 4649 4650// Str replacement when the result can fit in SmallStr. 4651static RawObject strReplaceSmallStr(const Str& src, const Str& oldstr, 4652 const Str& newstr, word count, 4653 word result_len) { 4654 DCHECK_BOUND(result_len, SmallStr::kMaxLength); 4655 word src_len = src.length(); 4656 word old_len = oldstr.length(); 4657 word new_len = newstr.length(); 4658 byte buffer[SmallStr::kMaxLength]; 4659 byte* dst = buffer; 4660 for (word i = 0, match_count = 0; i < src_len;) { 4661 if (match_count == count || !strHasPrefix(src, oldstr, i)) { 4662 *dst++ = src.byteAt(i++); 4663 continue; 4664 } 4665 newstr.copyTo(dst, new_len); 4666 dst += new_len; 4667 i += old_len; 4668 match_count++; 4669 } 4670 return SmallStr::fromBytes(View<byte>(buffer, result_len)); 4671} 4672 4673RawObject Runtime::strReplace(Thread* thread, const Str& src, const Str& oldstr, 4674 const Str& newstr, word count) { 4675 word src_len = src.length(); 4676 if (count < 0) { 4677 count = SmallInt::kMaxValue; // PY_SSIZE_T_MAX. 4678 } else if (count == 0 || src_len == 0) { 4679 return *src; 4680 } 4681 4682 if (oldstr.equals(*newstr)) { 4683 return *src; 4684 } 4685 4686 // Update the count to the number of occurences of oldstr in src, capped by 4687 // the given count. 4688 count = strCountSubStr(src, oldstr, count); 4689 if (count == 0) { 4690 return *src; 4691 } 4692 4693 word old_len = oldstr.length(); 4694 word new_len = newstr.length(); 4695 word result_len = src_len + (new_len - old_len) * count; 4696 if (result_len <= SmallStr::kMaxLength) { 4697 return strReplaceSmallStr(src, oldstr, newstr, count, result_len); 4698 } 4699 4700 HandleScope scope(thread); 4701 LargeStr result(&scope, createLargeStr(result_len)); 4702 word diff = new_len - old_len; 4703 word offset = 0; 4704 word match_count = 0; 4705 word i; 4706 for (i = 0; i < src_len && match_count < count;) { 4707 // TODO(T41400083): Use a different search algorithm 4708 if (strHasPrefix(src, oldstr, i)) { 4709 byte* dst = reinterpret_cast<byte*>(LargeStr::cast(*result).address()); 4710 newstr.copyTo(dst + i + offset, new_len); 4711 match_count++; 4712 offset += diff; 4713 i += old_len; 4714 continue; 4715 } 4716 byte* dst = reinterpret_cast<byte*>(result.address()); 4717 dst[i + offset] = src.byteAt(i); 4718 i++; 4719 } 4720 4721 // Copy the rest of the string. 4722 if (i < src_len) { 4723 if (src.isLargeStr()) { 4724 byte* src_byte = reinterpret_cast<byte*>(LargeStr::cast(*src).address()); 4725 byte* dst = reinterpret_cast<byte*>(result.address()); 4726 std::memcpy(dst + i + offset, src_byte + i, src_len - i); 4727 } else { 4728 for (; i < src_len; i++) { 4729 byte* dst = reinterpret_cast<byte*>(result.address()); 4730 dst[i + offset] = src.byteAt(i); 4731 } 4732 } 4733 } 4734 4735 return *result; 4736} 4737 4738// TODO(T30392425) Ensure thread safety 4739word Runtime::nextModuleIndex() { return ++next_module_index_; } 4740 4741} // namespace py