Path: blob/master/src/hotspot/share/memory/allocation.cpp
40949 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "memory/allocation.hpp"26#include "memory/allocation.inline.hpp"27#include "memory/arena.hpp"28#include "memory/metaspace.hpp"29#include "memory/resourceArea.hpp"30#include "runtime/os.hpp"31#include "runtime/task.hpp"32#include "runtime/threadCritical.hpp"33#include "services/memTracker.hpp"34#include "utilities/ostream.hpp"3536// allocate using malloc; will fail if no memory available37char* AllocateHeap(size_t size,38MEMFLAGS flags,39const NativeCallStack& stack,40AllocFailType alloc_failmode /* = AllocFailStrategy::EXIT_OOM*/) {41char* p = (char*) os::malloc(size, flags, stack);42if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {43vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "AllocateHeap");44}45return p;46}4748char* AllocateHeap(size_t size,49MEMFLAGS flags,50AllocFailType alloc_failmode /* = AllocFailStrategy::EXIT_OOM*/) {51return AllocateHeap(size, flags, CALLER_PC);52}5354char* ReallocateHeap(char *old,55size_t size,56MEMFLAGS flag,57AllocFailType alloc_failmode) {58char* p = (char*) os::realloc(old, size, flag, CALLER_PC);59if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {60vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "ReallocateHeap");61}62return p;63}6465// handles NULL pointers66void FreeHeap(void* p) {67os::free(p);68}6970void* MetaspaceObj::_shared_metaspace_base = NULL;71void* MetaspaceObj::_shared_metaspace_top = NULL;7273void* StackObj::operator new(size_t size) throw() { ShouldNotCallThis(); return 0; }74void StackObj::operator delete(void* p) { ShouldNotCallThis(); }75void* StackObj::operator new [](size_t size) throw() { ShouldNotCallThis(); return 0; }76void StackObj::operator delete [](void* p) { ShouldNotCallThis(); }7778void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,79size_t word_size,80MetaspaceObj::Type type, TRAPS) throw() {81// Klass has its own operator new82return Metaspace::allocate(loader_data, word_size, type, THREAD);83}8485void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,86size_t word_size,87MetaspaceObj::Type type) throw() {88assert(!Thread::current()->is_Java_thread(), "only allowed by non-Java thread");89return Metaspace::allocate(loader_data, word_size, type);90}9192bool MetaspaceObj::is_valid(const MetaspaceObj* p) {93// Weed out obvious bogus values first without traversing metaspace94if ((size_t)p < os::min_page_size()) {95return false;96} else if (!is_aligned((address)p, sizeof(MetaWord))) {97return false;98}99return Metaspace::contains((void*)p);100}101102void MetaspaceObj::print_address_on(outputStream* st) const {103st->print(" {" INTPTR_FORMAT "}", p2i(this));104}105106void* ResourceObj::operator new(size_t size, Arena *arena) throw() {107address res = (address)arena->Amalloc(size);108DEBUG_ONLY(set_allocation_type(res, ARENA);)109return res;110}111112void* ResourceObj::operator new [](size_t size, Arena *arena) throw() {113address res = (address)arena->Amalloc(size);114DEBUG_ONLY(set_allocation_type(res, ARENA);)115return res;116}117118void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) throw() {119address res = NULL;120switch (type) {121case C_HEAP:122res = (address)AllocateHeap(size, flags, CALLER_PC);123DEBUG_ONLY(set_allocation_type(res, C_HEAP);)124break;125case RESOURCE_AREA:126// new(size) sets allocation type RESOURCE_AREA.127res = (address)operator new(size);128break;129default:130ShouldNotReachHere();131}132return res;133}134135void* ResourceObj::operator new [](size_t size, allocation_type type, MEMFLAGS flags) throw() {136return (address) operator new(size, type, flags);137}138139void* ResourceObj::operator new(size_t size, const std::nothrow_t& nothrow_constant,140allocation_type type, MEMFLAGS flags) throw() {141// should only call this with std::nothrow, use other operator new() otherwise142address res = NULL;143switch (type) {144case C_HEAP:145res = (address)AllocateHeap(size, flags, CALLER_PC, AllocFailStrategy::RETURN_NULL);146DEBUG_ONLY(if (res!= NULL) set_allocation_type(res, C_HEAP);)147break;148case RESOURCE_AREA:149// new(size) sets allocation type RESOURCE_AREA.150res = (address)operator new(size, std::nothrow);151break;152default:153ShouldNotReachHere();154}155return res;156}157158void* ResourceObj::operator new [](size_t size, const std::nothrow_t& nothrow_constant,159allocation_type type, MEMFLAGS flags) throw() {160return (address)operator new(size, nothrow_constant, type, flags);161}162163void ResourceObj::operator delete(void* p) {164assert(((ResourceObj *)p)->allocated_on_C_heap(),165"delete only allowed for C_HEAP objects");166DEBUG_ONLY(((ResourceObj *)p)->_allocation_t[0] = (uintptr_t)badHeapOopVal;)167FreeHeap(p);168}169170void ResourceObj::operator delete [](void* p) {171operator delete(p);172}173174#ifdef ASSERT175void ResourceObj::set_allocation_type(address res, allocation_type type) {176// Set allocation type in the resource object177uintptr_t allocation = (uintptr_t)res;178assert((allocation & allocation_mask) == 0, "address should be aligned to 4 bytes at least: " INTPTR_FORMAT, p2i(res));179assert(type <= allocation_mask, "incorrect allocation type");180ResourceObj* resobj = (ResourceObj *)res;181resobj->_allocation_t[0] = ~(allocation + type);182if (type != STACK_OR_EMBEDDED) {183// Called from operator new(), set verification value.184resobj->_allocation_t[1] = (uintptr_t)&(resobj->_allocation_t[1]) + type;185}186}187188ResourceObj::allocation_type ResourceObj::get_allocation_type() const {189assert(~(_allocation_t[0] | allocation_mask) == (uintptr_t)this, "lost resource object");190return (allocation_type)((~_allocation_t[0]) & allocation_mask);191}192193bool ResourceObj::is_type_set() const {194allocation_type type = (allocation_type)(_allocation_t[1] & allocation_mask);195return get_allocation_type() == type &&196(_allocation_t[1] - type) == (uintptr_t)(&_allocation_t[1]);197}198199// This whole business of passing information from ResourceObj::operator new200// to the ResourceObj constructor via fields in the "object" is technically UB.201// But it seems to work within the limitations of HotSpot usage (such as no202// multiple inheritance) with the compilers and compiler options we're using.203// And it gives some possibly useful checking for misuse of ResourceObj.204void ResourceObj::initialize_allocation_info() {205if (~(_allocation_t[0] | allocation_mask) != (uintptr_t)this) {206// Operator new() is not called for allocations207// on stack and for embedded objects.208set_allocation_type((address)this, STACK_OR_EMBEDDED);209} else if (allocated_on_stack()) { // STACK_OR_EMBEDDED210// For some reason we got a value which resembles211// an embedded or stack object (operator new() does not212// set such type). Keep it since it is valid value213// (even if it was garbage).214// Ignore garbage in other fields.215} else if (is_type_set()) {216// Operator new() was called and type was set.217assert(!allocated_on_stack(),218"not embedded or stack, this(" PTR_FORMAT ") type %d a[0]=(" PTR_FORMAT ") a[1]=(" PTR_FORMAT ")",219p2i(this), get_allocation_type(), _allocation_t[0], _allocation_t[1]);220} else {221// Operator new() was not called.222// Assume that it is embedded or stack object.223set_allocation_type((address)this, STACK_OR_EMBEDDED);224}225_allocation_t[1] = 0; // Zap verification value226}227228ResourceObj::ResourceObj() {229initialize_allocation_info();230}231232ResourceObj::ResourceObj(const ResourceObj&) {233// Initialize _allocation_t as a new object, ignoring object being copied.234initialize_allocation_info();235}236237ResourceObj& ResourceObj::operator=(const ResourceObj& r) {238assert(allocated_on_stack(),239"copy only into local, this(" PTR_FORMAT ") type %d a[0]=(" PTR_FORMAT ") a[1]=(" PTR_FORMAT ")",240p2i(this), get_allocation_type(), _allocation_t[0], _allocation_t[1]);241// Keep current _allocation_t value;242return *this;243}244245ResourceObj::~ResourceObj() {246// allocated_on_C_heap() also checks that encoded (in _allocation) address == this.247if (!allocated_on_C_heap()) { // ResourceObj::delete() will zap _allocation for C_heap.248_allocation_t[0] = (uintptr_t)badHeapOopVal; // zap type249}250}251#endif // ASSERT252253//--------------------------------------------------------------------------------------254// Non-product code255256#ifndef PRODUCT257void AllocatedObj::print() const { print_on(tty); }258void AllocatedObj::print_value() const { print_value_on(tty); }259260void AllocatedObj::print_on(outputStream* st) const {261st->print_cr("AllocatedObj(" INTPTR_FORMAT ")", p2i(this));262}263264void AllocatedObj::print_value_on(outputStream* st) const {265st->print("AllocatedObj(" INTPTR_FORMAT ")", p2i(this));266}267268ReallocMark::ReallocMark() {269#ifdef ASSERT270Thread *thread = Thread::current();271_nesting = thread->resource_area()->nesting();272#endif273}274275void ReallocMark::check() {276#ifdef ASSERT277if (_nesting != Thread::current()->resource_area()->nesting()) {278fatal("allocation bug: array could grow within nested ResourceMark");279}280#endif281}282283#endif // Non-product284285286