Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/cpu/aarch32/vm/c1_MacroAssembler_aarch32.cpp
32285 views
/*1* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2014, Red Hat Inc. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/24// This file is a derivative work resulting from (and including) modifications25// made by Azul Systems, Inc. The dates of such changes are 2013-2016.26// Copyright 2013-2016 Azul Systems, Inc. All Rights Reserved.27//28// Please contact Azul Systems, 385 Moffett Park Drive, Suite 115, Sunnyvale,29// CA 94089 USA or visit www.azul.com if you need additional information or30// have any questions.3132#include "precompiled.hpp"33#include "c1/c1_MacroAssembler.hpp"34#include "c1/c1_Runtime1.hpp"35#include "classfile/systemDictionary.hpp"36#include "gc_interface/collectedHeap.hpp"37#include "interpreter/interpreter.hpp"38#include "oops/arrayOop.hpp"39#include "oops/markOop.hpp"40#include "runtime/basicLock.hpp"41#include "runtime/biasedLocking.hpp"42#include "runtime/os.hpp"43#include "runtime/sharedRuntime.hpp"44#include "runtime/stubRoutines.hpp"4546void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result,47FloatRegister f0, FloatRegister f1,48Register result)49{50Label done;51if (is_float) {52vcmp_f32(f0, f1);53} else {54vcmp_f64(f0, f1);55}5657get_fpsr();5859mov(result, 0);60if (unordered_result < 0) {61// we want -1 for unordered or less than, 0 for equal and 1 for62// greater than.63mov(result, 1, NE); // Not equal or unordered64neg(result, result, LT); // Less than or unordered65} else {66// we want -1 for less than, 0 for equal and 1 for unordered or67// greater than.68mov(result, 1, NE); // Not equal or unordered69neg(result, result, LO); // Less than70}71}7273int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register scratch, Label& slow_case) {74const int aligned_mask = BytesPerWord -1;75const int hdr_offset = oopDesc::mark_offset_in_bytes();76assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");77Label done, fail;78int null_check_offset = -1;7980verify_oop(obj);8182// save object being locked into the BasicObjectLock83str(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));8485if (UseBiasedLocking) {86assert(scratch != noreg, "should have scratch register at this point");87null_check_offset = biased_locking_enter(disp_hdr, obj, hdr, scratch, false, done, &slow_case);88} else {89null_check_offset = offset();90}9192// Load object header93ldr(hdr, Address(obj, hdr_offset));94// and mark it as unlocked95orr(hdr, hdr, markOopDesc::unlocked_value);96// save unlocked object header into the displaced header location on the stack97str(hdr, Address(disp_hdr, 0));98// test if object header is still the same (i.e. unlocked), and if so, store the99// displaced header address in the object header - if it is not the same, get the100// object header instead101lea(rscratch2, Address(obj, hdr_offset));102cmpxchgptr(hdr, disp_hdr, rscratch2, rscratch1, done, /*fallthough*/NULL);103// if the object header was the same, we're done104// if the object header was not the same, it is now in the hdr register105// => test if it is a stack pointer into the same stack (recursive locking), i.e.:106//107// 1) (hdr & aligned_mask) == 0108// 2) sp <= hdr109// 3) hdr <= sp + page_size110//111// these 3 tests can be done by evaluating the following expression:112//113// (hdr - sp) & (aligned_mask - page_size)114//115// assuming both the stack pointer and page_size have their least116// significant 2 bits cleared and page_size is a power of 2117mov(rscratch1, sp);118sub(hdr, hdr, rscratch1);119mov(rscratch2, aligned_mask - os::vm_page_size());120ands(hdr, hdr, rscratch2);121// for recursive locking, the result is zero => save it in the displaced header122// location (NULL in the displaced hdr location indicates recursive locking)123str(hdr, Address(disp_hdr, 0));124// otherwise we don't care about the result and handle locking via runtime call125cbnz(hdr, slow_case);126// done127bind(done);128if (PrintBiasedLockingStatistics) {129lea(rscratch2, ExternalAddress((address)BiasedLocking::fast_path_entry_count_addr()));130addmw(Address(rscratch2, 0), 1, rscratch1);131}132return null_check_offset;133}134135136void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {137const int aligned_mask = BytesPerWord -1;138const int hdr_offset = oopDesc::mark_offset_in_bytes();139assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");140Label done;141142if (UseBiasedLocking) {143// load object144ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));145biased_locking_exit(obj, hdr, done);146}147148// load displaced header149ldr(hdr, Address(disp_hdr, 0));150// if the loaded hdr is NULL we had recursive locking151// if we had recursive locking, we are done152cbz(hdr, done);153if (!UseBiasedLocking) {154// load object155ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));156}157verify_oop(obj);158// test if object header is pointing to the displaced header, and if so, restore159// the displaced header in the object - if the object header is not pointing to160// the displaced header, get the object header instead161// if the object header was not pointing to the displaced header,162// we do unlocking via runtime call163if (hdr_offset) {164lea(rscratch1, Address(obj, hdr_offset));165cmpxchgptr(disp_hdr, hdr, rscratch1, rscratch2, done, &slow_case);166} else {167cmpxchgptr(disp_hdr, hdr, obj, rscratch2, done, &slow_case);168}169// done170bind(done);171}172173174// Defines obj, preserves var_size_in_bytes175void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) {176if (UseTLAB) {177tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);178} else {179eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);180incr_allocated_bytes(noreg, var_size_in_bytes, con_size_in_bytes, t1);181}182}183184void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {185assert_different_registers(obj, klass, len);186if (UseBiasedLocking && !len->is_valid()) {187assert_different_registers(obj, klass, len, t1, t2);188ldr(t1, Address(klass, Klass::prototype_header_offset()));189} else {190// This assumes that all prototype bits fit in an int32_t191mov(t1, (int32_t)(intptr_t)markOopDesc::prototype());192}193str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));194str(klass, Address(obj, oopDesc::klass_offset_in_bytes()));195196if (len->is_valid()) {197str(len, Address(obj, arrayOopDesc::length_offset_in_bytes()));198}199}200201// Zero words; len is in bytes202// Destroys all registers except addr203// len must be a nonzero multiple of wordSize204void C1_MacroAssembler::zero_memory(Register addr, Register len, Register t1) {205assert_different_registers(addr, len, t1, rscratch1, rscratch2);206207#ifdef ASSERT208{ Label L;209tst(len, BytesPerWord - 1);210b(L, Assembler::EQ);211stop("len is not a multiple of BytesPerWord");212bind(L);213}214#endif215216#ifndef PRODUCT217block_comment("zero memory");218#endif219220Label loop;221Label entry;222223// Algorithm:224//225// scratch1 = cnt & 7;226// cnt -= scratch1;227// p += scratch1;228// switch (scratch1) {229// do {230// cnt -= 8;231// p[-8] = 0;232// case 7:233// p[-7] = 0;234// case 6:235// p[-6] = 0;236// // ...237// case 1:238// p[-1] = 0;239// case 0:240// p += 8;241// } while (cnt);242// }243244const int unroll = 8; // Number of str instructions we'll unroll245246lsr(len, len, LogBytesPerWord);247andr(rscratch1, len, unroll - 1); // tmp1 = cnt % unroll248sub(len, len, rscratch1); // cnt -= unroll249// t1 always points to the end of the region we're about to zero250add(t1, addr, rscratch1, lsl(LogBytesPerWord));251adr(rscratch2, entry);252sub(rscratch2, rscratch2, rscratch1, lsl(2));253mov(rscratch1, 0);254b(rscratch2);255bind(loop);256sub(len, len, unroll);257for (int i = -unroll; i < 0; i++)258str(rscratch1, Address(t1, i * wordSize));259bind(entry);260add(t1, t1, unroll * wordSize);261cbnz(len, loop);262}263264// preserves obj, destroys len_in_bytes265void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {266Label done;267assert(obj != len_in_bytes && obj != t1 && t1 != len_in_bytes, "registers must be different");268assert((hdr_size_in_bytes & (BytesPerWord - 1)) == 0, "header size is not a multiple of BytesPerWord");269Register index = len_in_bytes;270// index is positive and ptr sized271subs(index, index, hdr_size_in_bytes);272b(done, Assembler::EQ);273// note: for the remaining code to work, index must be a multiple of BytesPerWord274#ifdef ASSERT275{ Label L;276tst(index, BytesPerWord - 1);277b(L, Assembler::EQ);278stop("index is not a multiple of BytesPerWord");279bind(L);280}281#endif282283// Preserve obj284if (hdr_size_in_bytes)285add(obj, obj, hdr_size_in_bytes);286zero_memory(obj, index, t1);287if (hdr_size_in_bytes)288sub(obj, obj, hdr_size_in_bytes);289290// done291bind(done);292}293294295void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) {296assert_different_registers(obj, t1, t2); // XXX really?297assert(header_size >= 0 && object_size >= header_size, "illegal sizes");298299try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);300301initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2);302}303304// This method clobbers t1, t2, and rscratch1 registers.305void C1_MacroAssembler::initialize_object(Register obj, Register klass,306Register var_size_in_bytes,307int con_size_in_bytes,308Register t1, Register t2) {309assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,310"con_size_in_bytes is not multiple of alignment");311312const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;313314initialize_header(obj, klass, noreg, t1, t2);315316// Null out rest of allocated space317const Register index = t2;318const int threshold = 8 * BytesPerWord;319if (var_size_in_bytes != noreg) {320mov(index, var_size_in_bytes);321initialize_body(obj, index, hdr_size_in_bytes, t1);322} else if (con_size_in_bytes <= threshold) {323// Emit required number of str instructions (unroll loop completely)324mov(t1, 0);325for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord) {326str(t1, Address(obj, i));327}328} else if (con_size_in_bytes > hdr_size_in_bytes) {329// Use loop to null out fields330int words = (con_size_in_bytes - hdr_size_in_bytes) / BytesPerWord;331mov(t1, 0);332333const int unroll = 4; // Number of str instructions we'll unroll334mov(index, words / unroll);335int remainder = words % unroll;336lea(rscratch1, Address(obj, hdr_size_in_bytes + remainder * BytesPerWord));337338Label entry_point, loop;339b(entry_point);340bind(loop);341sub(index, index, 1);342for (int i = -unroll; i < 0; i++) {343if (-i == remainder) {344bind(entry_point);345}346str(t1, Address(rscratch1, i * BytesPerWord));347}348if (remainder == 0) {349bind(entry_point);350}351add(rscratch1, rscratch1, unroll * BytesPerWord);352cbnz(index, loop);353}354355membar(StoreStore);356357if (CURRENT_ENV->dtrace_alloc_probes()) {358assert(obj == r0, "must be");359far_call(RuntimeAddress(Runtime1::entry_for(360Runtime1::dtrace_object_alloc_id)));361}362363verify_oop(obj);364}365366void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int header_size, int f, Register klass, Label& slow_case) {367assert_different_registers(obj, len, t1, t2, klass);368369// determine alignment mask370assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work");371372// check for negative or excessive length373mov(rscratch1, (int32_t)max_array_allocation_length);374cmp(len, rscratch1);375b(slow_case, Assembler::HS);376377const Register arr_size = t2; // okay to be the same378// align object end379mov(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask);380add(arr_size, arr_size, len, Assembler::lsl(f));381mov(t1, ~MinObjAlignmentInBytesMask);382andr(arr_size, arr_size, t1);383384try_allocate(obj, arr_size, 0, t1, t2, slow_case);385386initialize_header(obj, klass, len, t1, t2);387388// clear rest of allocated space389const Register len_zero = len;390initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);391392membar(StoreStore);393394if (CURRENT_ENV->dtrace_alloc_probes()) {395assert(obj == r0, "must be");396far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));397}398399verify_oop(obj);400}401402403void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {404verify_oop(receiver);405// explicit NULL check not needed since load from [klass_offset] causes a trap406// check against inline cache407assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");408409cmp_klass(receiver, iCache, rscratch1);410}411412void C1_MacroAssembler::build_frame(int frame_size_in_bytes,413int bang_size_in_bytes) {414assert(bang_size_in_bytes >= frame_size_in_bytes,415"stack bang size incorrect");416417// If we have to make this method not-entrant, we'll overwrite its first418// instruction with a jump. For this action to be legal we must ensure that419// this first instruction is a B, BL, NOP, BKPT, or SVC. Make it a NOP420nop();421422// Make sure there is enough stack space for this method's activation423generate_stack_overflow_check(bang_size_in_bytes);424425// Push lr, rfp, and optionally update rfp. rfp points to the first stack426// word used by the new frame.427stmdb(sp, RegSet::of(rfp, lr).bits());428if (PreserveFramePointer) {429add(rfp, sp, BytesPerWord);430}431432// Create frame. frame_size_in_bytes always comes from433// LIR_Assembler::initial_frame_size_in_bytes() method, and it already434// takes into account two stack words spent on saving lr and rfp.435decrement(sp, frame_size_in_bytes);436}437438void C1_MacroAssembler::remove_frame(int frame_size_in_bytes) {439// Remove frame. frame_size_in_bytes always comes from440// LIR_Assembler::initial_frame_size_in_bytes() method, and it already441// takes into account two stack words spent on saving lr and rfp.442increment(sp, frame_size_in_bytes);443444// Pop rfp and lr445ldmia(sp, RegSet::of(rfp, lr).bits());446}447448void C1_MacroAssembler::verified_entry() {449}450451void C1_MacroAssembler::patchable_load(Register reg, address addr) {452nop();453membar(Assembler::LoadLoad);454far_load(reg, addr);455}456457#ifndef PRODUCT458459void C1_MacroAssembler::verify_stack_oop(int stack_offset) {460if (!VerifyOops) return;461verify_oop_addr(Address(sp, stack_offset), "oop");462}463464void C1_MacroAssembler::verify_not_null_oop(Register r) {465if (!VerifyOops) return;466Label not_null;467cbnz(r, not_null);468stop("non-null oop required");469bind(not_null);470verify_oop(r);471}472473void C1_MacroAssembler::invalidate_registers(bool inv_r0, bool inv_r2, bool inv_r3) {474#ifdef ASSERT475static int nn;476if (inv_r0) mov(r0, 0xDEAD);477if (inv_r2) mov(r2, nn++);478if (inv_r3) mov(r3, 0xDEAD);479#endif480}481#endif // ifndef PRODUCT482483484