blob: fb5977fc3d8075e2b8a272fddff73356401b113f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_DOMAIN "vm.core"
#include "cxxlog.h"
#include "open/vm_properties.h"
#include "open/vm_type_access.h"
#include "open/vm_field_access.h"
#include "open/vm_method_access.h"
#include "open/vm_class_loading.h"
#include "open/vm_class_manipulation.h"
#include "open/vm_class_info.h"
#include "open/vm_ee.h"
#include "classloader.h"
#include "class_interface.h"
#include "Package.h"
#include "vtable.h"
#include "vm_arrays.h"
#include "compile.h"
#include "port_mutex.h"
#include "cci.h"
#include "nogc.h"
#include "exceptions.h"
BOOLEAN class_is_final(Class_Handle cl) {
assert(cl);
return cl->is_final();
}
BOOLEAN class_is_abstract(Class_Handle cl) {
assert(cl);
return cl->is_abstract();
}
BOOLEAN class_is_interface(Class_Handle cl) {
assert(cl);
return cl->is_interface();
}
BOOLEAN class_is_array(Class_Handle cl) {
assert(cl);
return cl->is_array();
} //class_is_array
static unsigned countLeadingChars(const char* str, char c) {
U_32 n=0;
while (str[n]==c) {
n++;
}
return n;
}
unsigned class_cp_get_num_array_dimensions(Class_Handle cl, unsigned short cpIndex) {
ConstantPool& cp = cl->get_constant_pool();
unsigned char tag = cp.get_tag(cpIndex);
char c = '[';
switch (tag) {
case CONSTANT_Class: {
uint16 nameIdx = cp.get_class_name_index(cpIndex);
const char* str = cp.get_utf8_string(nameIdx)->bytes;
return countLeadingChars(str, c);
}
case CONSTANT_Fieldref: {
const char* str = class_cp_get_entry_descriptor(cl, cpIndex);
return countLeadingChars(str, c);
}
default:
assert(0);
}
return 0;
}
const char* class_get_package_name(Class_Handle cl) {
assert(cl);
return cl->get_package()->get_name()->bytes;
}
BOOLEAN method_is_abstract(Method_Handle m) {
assert(m);
return m->is_abstract();
} // method_is_abstract
BOOLEAN field_is_static(Field_Handle f)
{
assert(f);
return f->is_static();
}
BOOLEAN field_is_final(Field_Handle f)
{
assert(f);
return f->is_final();
}
BOOLEAN field_is_volatile(Field_Handle f)
{
assert(f);
return f->is_volatile();
}
BOOLEAN field_is_private(Field_Handle f)
{
assert(f);
return f->is_private();
}
BOOLEAN field_is_public(Field_Handle f)
{
assert(f);
return f->is_public();
}
unsigned field_get_offset(Field_Handle f)
{
assert(f);
assert(!f->is_static());
return f->get_offset();
} //field_get_offset
void* field_get_address(Field_Handle f)
{
assert(f);
assert(f->is_static());
return f->get_address();
} // field_get_address
const char* field_get_name(Field_Handle f)
{
assert(f);
return f->get_name()->bytes;
}
const char* field_get_descriptor(Field_Handle f)
{
assert(f);
return f->get_descriptor()->bytes;
}
Java_Type field_get_type(Field_Handle f)
{
assert(f);
return f->get_java_type();
} // field_get_type
unsigned field_get_flags(Field_Handle f)
{
assert(f);
return f->get_access_flags();
}
Class_Handle field_get_class(Field_Handle f)
{
assert(f);
return f->get_class();
} //field_get_class
void field_get_track_access_flag(Field_Handle f, char** address,
char* mask)
{
return f->get_track_access_flag(address, mask);
}
void field_get_track_modification_flag(Field_Handle f, char** address,
char* mask)
{
return f->get_track_modification_flag(address, mask);
}
BOOLEAN method_is_static(Method_Handle m)
{
assert(m);
return m->is_static();
} // method_is_static
BOOLEAN method_is_final(Method_Handle m)
{
assert(m);
return m->is_final();
} // method_is_final
BOOLEAN method_is_synchronized(Method_Handle m)
{
assert(m);
return m->is_synchronized();
} // method_is_synchronized
BOOLEAN method_is_private(Method_Handle m)
{
assert(m);
return m->is_private();
} // method_is_private
BOOLEAN method_is_strict(Method_Handle m)
{
assert(m);
return m->is_strict();
} // method_is_strict
BOOLEAN method_is_native(Method_Handle m)
{
assert(m);
return m->is_native();
} // method_is_native
U_8* method_allocate_info_block(Method_Handle m, JIT_Handle j, size_t size)
{
assert(m);
return (U_8*)(m->allocate_jit_info_block(size, (JIT *)j));
} //method_allocate_info_block
U_8* method_allocate_jit_data_block(Method_Handle m, JIT_Handle j, size_t size, size_t alignment)
{
assert(m);
return (U_8*)(m->allocate_JIT_data_block(size, (JIT *)j, alignment));
} //method_allocate_jit_data_block
U_8* method_get_info_block_jit(Method_Handle m, JIT_Handle j)
{
assert(m);
CodeChunkInfo *jit_info = m->get_chunk_info_no_create_mt((JIT *)j, CodeChunkInfo::main_code_chunk_id);
if (jit_info == NULL) {
return NULL;
}
return (U_8*)jit_info->_jit_info_block;
} //method_get_info_block_jit
unsigned method_get_info_block_size_jit(Method_Handle m, JIT_Handle j)
{
assert(m);
CodeChunkInfo *jit_info = ((Method *)m)->get_chunk_info_no_create_mt((JIT *)j, CodeChunkInfo::main_code_chunk_id);
return jit_info == 0 ? 0 : (unsigned) jit_info->_jit_info_block_size;
} //method_get_info_block_size_jit
U_8* method_allocate_data_block(Method_Handle m, JIT_Handle j, size_t size, size_t alignment)
{
assert(m);
return (U_8*)(m->allocate_rw_data_block(size, alignment, (JIT*)j));
} //method_allocate_data_block
U_8*
method_allocate_code_block(Method_Handle m,
JIT_Handle j,
size_t size,
size_t alignment,
CodeBlockHeat heat,
int id,
Code_Allocation_Action action)
{
assert(m);
JIT *jit = (JIT *)j;
assert(jit);
U_32 drlHeat;
if (heat == CodeBlockHeatMin)
drlHeat = CODE_BLOCK_HEAT_COLD;
else if (heat == CodeBlockHeatMax)
drlHeat = CODE_BLOCK_HEAT_MAX/2;
else {
assert (heat == CodeBlockHeatDefault);
drlHeat = CODE_BLOCK_HEAT_DEFAULT;
}
// the following method is safe to call from multiple threads
U_8* code_block = (U_8*)m->allocate_code_block_mt(size, alignment, jit, drlHeat, id, action);
return code_block;
} // method_allocate_code_block
U_8* method_get_code_block_jit(Method_Handle m, JIT_Handle j)
{
assert(m);
return method_get_code_block_addr_jit_new(m, j, 0);
} //method_get_code_block_addr_jit
unsigned method_get_code_block_size_jit(Method_Handle m, JIT_Handle j)
{
assert(m);
return method_get_code_block_size_jit_new(m, j, 0);
} //method_get_code_block_size_jit
U_8* method_get_code_block_addr_jit_new(Method_Handle method,
JIT_Handle j,
int id)
{
assert(method);
CodeChunkInfo* jit_info = method->get_chunk_info_no_create_mt((JIT *)j, id);
assert(jit_info);
return (U_8*)jit_info->get_code_block_addr();
} //method_get_code_block_addr_jit_new
unsigned method_get_code_block_size_jit_new(Method_Handle method,
JIT_Handle j,
int id)
{
assert(method);
CodeChunkInfo *jit_info = ((Method *)method)->get_chunk_info_no_create_mt((JIT *)j, id);
return jit_info == 0 ? 0 :(unsigned) jit_info->get_code_block_size();
} //method_get_code_block_size_jit_new
const U_8* method_get_bytecode(Method_Handle m)
{
assert(m);
return m->get_byte_code_addr();
}
U_32
method_get_bytecode_length(Method_Handle m)
{
assert(m);
return m->get_byte_code_size();
}
U_32 method_get_max_locals(Method_Handle m)
{
assert(m);
return m->get_max_locals();
}
uint16 method_get_max_stack(Method_Handle m)
{
assert(m);
return m->get_max_stack();
}
size_t method_get_vtable_offset(Method_Handle m)
{
assert(m);
return m->get_offset();
}
void *method_get_indirect_address(Method_Handle m)
{
assert(m);
return m->get_indirect_address();
} //method_get_indirect_address
const char *
method_get_name(Method_Handle m)
{
assert(m);
return m->get_name()->bytes;
}
const char* method_get_descriptor(Method_Handle m)
{
assert(m);
return m->get_descriptor()->bytes;
}
Class_Handle method_get_class(Method_Handle m)
{
assert(m);
return m->get_class();
}
void method_lock(Method_Handle m)
{
assert(m);
return m->lock();
}
void method_unlock(Method_Handle m)
{
assert(m);
return m->unlock();
}
Java_Type method_get_return_type(Method_Handle m)
{
assert(m);
return m->get_return_java_type();
}
BOOLEAN method_is_overridden(Method_Handle m)
{
assert(m);
return m->is_overridden();
} // method_is_overridden
const char* class_get_name(Class_Handle cl)
{
assert(cl);
return cl->get_name()->bytes;
} //class_get_name
unsigned short class_get_version(Class_Handle klass)
{
assert(klass);
return klass->get_version();
} // class_get_version
unsigned class_get_flags(Class_Handle cl)
{
assert(cl);
return cl->get_access_flags();
} //class_get_flags
U_32 class_get_depth(Class_Handle cl)
{
assert(cl);
return cl->get_depth();
} //class_get_depth
BOOLEAN class_is_support_fast_instanceof(Class_Handle cl)
{
assert(cl);
return cl->get_fast_instanceof_flag();
} //class_get_depth
Class_Handle vtable_get_class(VTable_Handle vh) {
return vh->clss;
} // vtable_get_class
BOOLEAN class_is_initialized(Class_Handle ch)
{
assert(ch);
return ch->is_initialized();
} //class_is_initialized
Class_Handle class_get_super_class(Class_Handle cl)
{
assert(cl);
return cl->get_super_class();
} // class_get_super_class
Class_Handle class_get_extended_class(Class_Handle klass, const char* super_name)
{
assert(klass);
assert(super_name);
Global_Env* env = VM_Global_State::loader_env;
String* pooled_name = env->string_pool.lookup(super_name);
for(Class* clss = klass; clss; clss = clss->get_super_class()) {
if(clss->get_name() == pooled_name) {
// found class with given name
return clss;
}
}
return NULL;
} // class_get_extended_class
unsigned class_number_implements(Class_Handle ch)
{
assert(ch);
return ch->get_number_of_superinterfaces();
}
Class_Handle class_get_implements(Class_Handle ch, unsigned idx)
{
assert(ch);
return ch->get_superinterface(idx);
}
Class_Handle class_get_declaring_class(Class_Handle ch)
{
return ch->resolve_declaring_class(VM_Global_State::loader_env);
}
unsigned class_number_inner_classes(Class_Handle ch)
{
assert(ch);
return ch->get_number_of_inner_classes();
}
Boolean class_is_inner_class_public(Class_Handle ch, unsigned idx)
{
assert(ch);
return (ch->get_inner_class_access_flags(idx) & ACC_PUBLIC) != 0;
}
Class_Handle class_get_inner_class(Class_Handle ch, unsigned idx)
{
assert(ch);
uint16 cp_index = ch->get_inner_class_index(idx);
return ch->_resolve_class(VM_Global_State::loader_env, cp_index);
}
BOOLEAN class_is_instanceof(Class_Handle s, Class_Handle t)
{
assert(s);
assert(t);
return class_is_subtype(s, t);
} // class_is_instanceof
unsigned class_get_array_element_size(Class_Handle ch)
{
assert(ch);
return ch->get_array_element_size();
}
Class_Handle class_get_array_element_class(Class_Handle cl)
{
assert(cl);
return cl->get_array_element_class();
} //class_get_array_element_class
BOOLEAN class_is_throwable(Class_Handle ch)
{
assert(ch);
Global_Env *env = VM_Global_State::loader_env;
Class *exc_base_clss = env->java_lang_Throwable_Class;
while(ch != NULL) {
if(ch == exc_base_clss) {
return TRUE;
}
//sundr printf("class name before super: %s %p\n", ch->name->bytes, ch);
ch = class_get_super_class(ch);
}
return FALSE;
} // class_is_throwable
Class_Handle class_get_class_of_primitive_type(VM_Data_Type typ)
{
Global_Env *env = VM_Global_State::loader_env;
Class *clss = NULL;
switch(typ) {
case VM_DATA_TYPE_INT8:
clss = env->Byte_Class;
break;
case VM_DATA_TYPE_INT16:
clss = env->Short_Class;
break;
case VM_DATA_TYPE_INT32:
clss = env->Int_Class;
break;
case VM_DATA_TYPE_INT64:
clss = env->Long_Class;
break;
case VM_DATA_TYPE_F8:
clss = env->Double_Class;
break;
case VM_DATA_TYPE_F4:
clss = env->Float_Class;
break;
case VM_DATA_TYPE_BOOLEAN:
clss = env->Boolean_Class;
break;
case VM_DATA_TYPE_CHAR:
clss = env->Char_Class;
break;
case VM_DATA_TYPE_VOID:
clss = env->Void_Class;
break;
case VM_DATA_TYPE_INTPTR:
case VM_DATA_TYPE_UINTPTR:
case VM_DATA_TYPE_UINT8:
case VM_DATA_TYPE_UINT16:
case VM_DATA_TYPE_UINT32:
case VM_DATA_TYPE_UINT64:
clss = NULL; // to allow star jit initialization
break;
default:
LDIE(69, "Unknown vm data type"); // We need a better way to indicate an internal error
}
return clss;
} // class_get_class_of_primitive_type
VTable_Handle class_get_vtable(Class_Handle cl)
{
assert(cl);
return cl->get_vtable();
} //class_get_vtable
const char* class_get_source_file_name(Class_Handle cl)
{
assert(cl);
if(!cl->has_source_information())
return NULL;
return cl->get_source_file_name();
} // class_get_source_file_name
const char* class_cp_get_const_string(Class_Handle cl, U_16 index)
{
assert(cl);
return cl->get_constant_pool().get_string_chars(index);
} //class_get_const_string
// Returns the address where the interned version of the string is stored: this will be the address
// of a slot containing a Java_java_lang_String* or a U_32 compressed reference. Also interns the
// string so that the JIT can load a reference to the interned string without checking if it is null.
const void *class_get_const_string_intern_addr(Class_Handle cl, unsigned short index)
{
assert(cl);
Global_Env* env = VM_Global_State::loader_env;
String* str = cl->get_constant_pool().get_string(index);
assert(str);
assert((void *)(&(str->intern.raw_ref)) == (void *)(&(str->intern.compressed_ref)));
return &(str->intern.raw_ref);
} //class_get_const_string_intern_addr
const char* class_cp_get_entry_descriptor(Class_Handle src_class, unsigned short index)
{
ConstantPool& cp = src_class->get_constant_pool();
if(!(cp.is_fieldref(index)
|| cp.is_methodref(index)
|| cp.is_interfacemethodref(index)))
{
return NULL;
}
index = cp.get_ref_name_and_type_index(index);
index = cp.get_name_and_type_descriptor_index(index);
return cp.get_utf8_chars(index);
} // class_cp_get_entry_descriptor
VM_Data_Type class_cp_get_field_type(Class_Handle src_class, U_16 cp_index)
{
assert(src_class->get_constant_pool().is_fieldref(cp_index));
char class_id = (class_cp_get_entry_descriptor(src_class, cp_index))[0];
switch(class_id)
{
case VM_DATA_TYPE_BOOLEAN:
case VM_DATA_TYPE_CHAR:
case VM_DATA_TYPE_INT8:
case VM_DATA_TYPE_INT16:
case VM_DATA_TYPE_INT32:
case VM_DATA_TYPE_INT64:
case VM_DATA_TYPE_F4:
case VM_DATA_TYPE_F8:
return (VM_Data_Type)class_id;
case VM_DATA_TYPE_ARRAY:
case VM_DATA_TYPE_CLASS:
return VM_DATA_TYPE_CLASS;
default:
LDIE(69, "Unknown vm data type");
}
return VM_DATA_TYPE_INVALID;
} // class_cp_get_field_type
VM_Data_Type class_cp_get_const_type(Class_Handle cl, U_16 index)
{
assert(cl);
Java_Type jt = JAVA_TYPE_INVALID;
ConstantPool& cp = cl->get_constant_pool();
switch(cp.get_tag(index)) {
case CONSTANT_String:
jt = JAVA_TYPE_STRING;
break;
case CONSTANT_Integer:
jt = JAVA_TYPE_INT;
break;
case CONSTANT_Float:
jt = JAVA_TYPE_FLOAT;
break;
case CONSTANT_Long:
jt = JAVA_TYPE_LONG;
break;
case CONSTANT_Double:
jt = JAVA_TYPE_DOUBLE;
break;
case CONSTANT_Class:
jt = JAVA_TYPE_CLASS;
break;
case CONSTANT_UnusedEntry:
if(cp.get_tag(index - 1) == CONSTANT_Double) {
jt = JAVA_TYPE_DOUBLE;
break;
} else if(cp.get_tag(index - 1) == CONSTANT_Long) {
jt = JAVA_TYPE_LONG;
break;
}
default:
LDIE(5, "non-constant type is requested from constant pool : {0}" << cp.get_tag(index));
}
return (VM_Data_Type)jt;
} //class_cp_get_const_type
const void *class_cp_get_const_addr(Class_Handle cl, U_16 index)
{
assert(cl);
return cl->get_constant_pool().get_address_of_constant(index);
} //class_cp_get_const_addr
void* method_get_native_func_addr(Method_Handle method) {
return (void*)classloader_find_native(method);
}
Arg_List_Iterator method_get_argument_list(Method_Handle m)
{
assert(m);
return (Arg_List_Iterator)((Method *)m)->get_argument_list();
}
Class_Handle resolve_class_from_constant_pool(Class_Handle c_handle, unsigned index)
{
assert(c_handle);
return c_handle->_resolve_class(VM_Global_State::loader_env, index);
}
Field_Handle class_resolve_nonstatic_field(Class_Handle clss, unsigned short cp_index)
{
assert(clss);
Field* f = clss->_resolve_field(VM_Global_State::loader_env, cp_index);
return (!f || f->is_static()) ? NULL : f;
} // class_resolve_nonstatic_field
Class_Loader_Handle
class_get_class_loader(Class_Handle ch)
{
assert(ch);
return ch->get_class_loader();
} //class_get_class_loader
Class_Handle
vm_load_class_with_bootstrap(const char *name)
{
Global_Env *env = VM_Global_State::loader_env;
String *n = env->string_pool.lookup(name);
return env->bootstrap_class_loader->LoadClass(env, n);
}
Class_Handle
vm_lookup_class_with_bootstrap(const char* name)
{
Global_Env *env = VM_Global_State::loader_env;
String *n = env->string_pool.lookup(name);
Class *clss = env->bootstrap_class_loader->LookupClass(n);
return (Class_Handle)clss;
}
Class_Handle
class_load_class_by_descriptor(const char *descr,
Class_Handle ch)
{
assert(ch);
Global_Env *env = VM_Global_State::loader_env;
String *n;
switch(descr[0]) {
case '[':
n = env->string_pool.lookup(descr);
break;
case 'L':
{
int len = (int) strlen(descr);
n = env->string_pool.lookup(descr + 1, len - 2);
}
break;
case 'B':
return env->Byte_Class;
case 'C':
return env->Char_Class;
case 'D':
return env->Double_Class;
case 'F':
return env->Float_Class;
case 'I':
return env->Int_Class;
case 'J':
return env->Long_Class;
case 'S':
return env->Short_Class;
case 'Z':
return env->Boolean_Class;
default:
n = 0;
}
assert(n);
return ch->get_class_loader()->LoadClass(env, n);;
} //class_load_class_by_descriptor
//
// The following do not cause constant pools to be resolve, if they are not
// resolved already
//
const char* class_cp_get_entry_name(Class_Handle cl, U_16 index)
{
assert(cl);
ConstantPool& const_pool = cl->get_constant_pool();
if (!(const_pool.is_fieldref(index)
|| const_pool.is_methodref(index)
|| const_pool.is_interfacemethodref(index)))
{
LDIE(70, "Wrong index");
return 0;
}
index = const_pool.get_ref_name_and_type_index(index);
index = const_pool.get_name_and_type_name_index(index);
return const_pool.get_utf8_chars(index);
} // class_cp_get_entry_name
const char* class_cp_get_entry_class_name(Class_Handle cl, unsigned short index)
{
assert(cl);
ConstantPool& const_pool = cl->get_constant_pool();
if (!(const_pool.is_fieldref(index)
|| const_pool.is_methodref(index)
|| const_pool.is_interfacemethodref(index)))
{
LDIE(70, "Wrong index");
return 0;
}
index = const_pool.get_ref_class_index(index);
return class_cp_get_class_name(cl,index);
} // class_cp_get_entry_class_name
const char* class_cp_get_class_name(Class_Handle cl, unsigned short index)
{
assert(cl);
ConstantPool& const_pool = cl->get_constant_pool();
if (!const_pool.is_class(index)) {
LDIE(70, "Wrong index");
return 0;
}
return const_pool.get_utf8_chars(const_pool.get_class_name_index(index));
} // class_cp_get_class_name
Class_Handle method_get_throws(Method_Handle mh, unsigned idx)
{
assert(hythread_is_suspend_enabled());
assert(mh);
Method* m = (Method*)mh;
String* exn_name = m->get_exception_name(idx);
if (!exn_name) return NULL;
ClassLoader* class_loader = m->get_class()->get_class_loader();
Class *c =
class_loader->LoadVerifyAndPrepareClass(VM_Global_State::loader_env, exn_name);
// if loading failed - exception should be raised
assert((!c && exn_raised()) || (c && !exn_raised()));
return c;
}
uint16 method_get_exc_handler_number(Method_Handle m)
{
assert(m);
return m->num_bc_exception_handlers();
} // method_get_exc_handler_number
void method_get_exc_handler_info(Method_Handle m,
uint16 handler_id,
uint16* begin_offset,
uint16* end_offset,
uint16* handler_offset,
uint16* handler_cpindex)
{
assert(m);
Handler* h = m->get_bc_exception_handler_info(handler_id);
*begin_offset = h->get_start_pc();
*end_offset = h->get_end_pc();
*handler_offset = h->get_handler_pc();
*handler_cpindex = h->get_catch_type_index();
}
void method_set_num_target_handlers(Method_Handle m,
JIT_Handle j,
unsigned num_handlers)
{
assert(m);
((Method *)m)->set_num_target_exception_handlers((JIT *)j, num_handlers);
} //method_set_num_target_handlers
void method_set_target_handler_info(Method_Handle m,
JIT_Handle j,
unsigned eh_number,
void *start_ip,
void *end_ip,
void *handler_ip,
Class_Handle catch_cl,
Boolean exc_obj_is_dead)
{
assert(m);
((Method *)m)->set_target_exception_handler_info((JIT *)j,
eh_number,
start_ip,
end_ip,
handler_ip,
(Class *)catch_cl,
(exc_obj_is_dead == TRUE));
} //method_set_target_handler_info
Method_Side_Effects method_get_side_effects(Method_Handle m)
{
assert(m);
return ((Method *)m)->get_side_effects();
} //method_get_side_effects
void method_set_side_effects(Method_Handle m, Method_Side_Effects mse)
{
assert(m);
((Method *)m)->set_side_effects(mse);
} //method_set_side_effects
Method_Handle class_lookup_method_recursively(Class_Handle clss,
const char *name,
const char *descr)
{
assert(clss);
return (Method_Handle) class_lookup_method_recursive((Class *)clss, name, descr);
} //class_lookup_method_recursively
size_t object_get_vtable_offset()
{
return 0;
} //object_get_vtable_offset
Class_Handle vm_get_system_object_class()
{
Global_Env *env = VM_Global_State::loader_env;
return env->JavaLangObject_Class;
} // vm_get_system_object_class
Class_Handle vm_get_system_class_class()
{
Global_Env *env = VM_Global_State::loader_env;
return env->JavaLangClass_Class;
} // vm_get_system_class_class
Class_Handle vm_get_system_string_class()
{
Global_Env *env = VM_Global_State::loader_env;
return env->JavaLangString_Class;
} // vm_get_system_string_class
BOOLEAN field_is_literal(Field_Handle fh)
{
assert(fh);
Field *f = (Field *)fh;
return f->get_const_value_index() != 0;
} //field_is_literal
int vector_first_element_offset_unboxed(Class_Handle element_type)
{
assert(element_type);
Class *clss = (Class *)element_type;
int offset = 0;
if(clss->is_primitive()) {
Global_Env *env = VM_Global_State::loader_env;
if(clss == env->Double_Class) {
offset = VM_VECTOR_FIRST_ELEM_OFFSET_8;
} else if(clss == env->Long_Class) {
offset = VM_VECTOR_FIRST_ELEM_OFFSET_8;
} else {
offset = VM_VECTOR_FIRST_ELEM_OFFSET_1_2_4;
}
} else {
offset = VM_VECTOR_FIRST_ELEM_OFFSET_REF;
}
assert(offset);
return offset;
} //vector_first_element_offset_unboxed
int vector_first_element_offset(VM_Data_Type element_type)
{
switch(element_type) {
case VM_DATA_TYPE_CLASS:
return VM_VECTOR_FIRST_ELEM_OFFSET_REF;
default:
{
Class_Handle elem_class = class_get_class_of_primitive_type(element_type);
return vector_first_element_offset_unboxed(elem_class);
}
}
} //vector_first_element_offset
int vector_first_element_offset_class_handle(Class_Handle element_type)
{
return vector_first_element_offset_unboxed(element_type);
//return VM_VECTOR_FIRST_ELEM_OFFSET_REF;
}
Boolean method_is_java(Method_Handle mh)
{
assert(mh);
return TRUE;
} //method_is_java
BOOLEAN class_is_enum(Class_Handle ch)
{
assert(ch);
return ch->is_enum() ? TRUE : FALSE;
} // class_is_enum
static Class *class_get_array_of_primitive_type(VM_Data_Type typ)
{
Global_Env *env = VM_Global_State::loader_env;
Class *clss = NULL;
switch(typ) {
case VM_DATA_TYPE_INT8:
clss = env->ArrayOfByte_Class;
break;
case VM_DATA_TYPE_INT16:
clss = env->ArrayOfShort_Class;
break;
case VM_DATA_TYPE_INT32:
clss = env->ArrayOfInt_Class;
break;
case VM_DATA_TYPE_INT64:
clss = env->ArrayOfLong_Class;
break;
case VM_DATA_TYPE_F8:
clss = env->ArrayOfDouble_Class;
break;
case VM_DATA_TYPE_F4:
clss = env->ArrayOfFloat_Class;
break;
case VM_DATA_TYPE_BOOLEAN:
clss = env->ArrayOfBoolean_Class;
break;
case VM_DATA_TYPE_CHAR:
clss = env->ArrayOfChar_Class;
break;
case VM_DATA_TYPE_UINT8:
case VM_DATA_TYPE_UINT16:
case VM_DATA_TYPE_UINT32:
case VM_DATA_TYPE_UINT64:
case VM_DATA_TYPE_INTPTR:
case VM_DATA_TYPE_UINTPTR:
default:
DIE(("Unexpected vm data type")); // We need a better way to indicate an internal error
break;
}
return clss;
} // class_get_array_of_primitive_type
BOOLEAN class_is_primitive(Class_Handle ch)
{
assert(ch);
return ch->is_primitive();
} // class_is_primitive
VM_Data_Type class_get_primitive_type_of_class(Class_Handle ch)
{
assert(ch);
Global_Env *env = VM_Global_State::loader_env;
if (ch == env->Boolean_Class)
return VM_DATA_TYPE_BOOLEAN;
if (ch == env->Char_Class)
return VM_DATA_TYPE_CHAR;
if (ch == env->Byte_Class)
return VM_DATA_TYPE_INT8;
if (ch == env->Short_Class)
return VM_DATA_TYPE_INT16;
if (ch == env->Int_Class)
return VM_DATA_TYPE_INT32;
if (ch == env->Long_Class)
return VM_DATA_TYPE_INT64;
if (ch == env->Float_Class)
return VM_DATA_TYPE_F4;
if (ch == env->Double_Class)
return VM_DATA_TYPE_F8;
return VM_DATA_TYPE_CLASS;
} // class_get_primitive_type_of_class
// Returns the number of arguments defined for the method.
// This number includes the this pointer (if present).
unsigned char method_args_get_number(Method_Signature_Handle mh)
{
assert(mh);
assert(!mh->sig);
return mh->method->get_num_args();
} // method_args_get_number
// 20020303 At the moment we resolve the return type eagerly, but
// arguments are resolved lazily. We should rewrite return type resolution
// to be lazy too.
void Method_Signature::initialize_from_java_method(Method *meth)
{
assert(meth);
num_args = meth->get_num_args();
ClassLoader* cl = meth->get_class()->get_class_loader();
const char* d = meth->get_descriptor()->bytes;
assert(d[0]=='(');
d++;
arg_type_descs = (TypeDesc**)STD_MALLOC(sizeof(TypeDesc*)*num_args);
assert(arg_type_descs);
unsigned cur = 0;
if (!meth->is_static()) {
arg_type_descs[cur] = type_desc_create_from_java_class(meth->get_class());
assert(arg_type_descs[cur]);
cur++;
}
while (d[0]!=')') {
assert(cur<num_args);
arg_type_descs[cur] = type_desc_create_from_java_descriptor(d, cl);
assert(arg_type_descs[cur]);
cur++;
// Advance d to next argument
while (d[0]=='[') d++;
d++;
if (d[-1]=='L') {
while(d[0]!=';') d++;
d++;
}
}
assert(cur==num_args);
d++;
return_type_desc = type_desc_create_from_java_descriptor(d, cl);
assert(return_type_desc);
} //Method_Signature::initialize_from_java_method
void Method_Signature::reset()
{
return_type_desc = 0;
if (arg_type_descs)
STD_FREE(arg_type_descs);
num_args = 0;
arg_type_descs = 0;
method = 0;
sig = 0;
} //Method_Signature::reset
void Method_Signature::initialize_from_method(Method *meth)
{
assert(meth);
reset();
method = meth;
initialize_from_java_method(meth);
} //Method_Signature::initialize_from_method
Method_Signature_Handle method_get_signature(Method_Handle mh)
{
assert(mh);
Method *m = (Method *)mh;
Method_Signature *ms = m->get_method_sig();
if(!ms) {
ms = new Method_Signature();
if (ms == NULL) {
exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError);
return NULL;
}
assert(ms);
ms->initialize_from_method(m);
m->set_method_sig(ms);
}
return ms;
} // method_get_signature
U_16 class_number_fields(Class_Handle ch)
{
assert(ch);
return ch->get_number_of_fields();
}
unsigned class_num_instance_fields(Class_Handle ch)
{
assert(ch);
return ch->get_number_of_fields() - ch->get_number_of_static_fields();
} //class_num_instance_fields
unsigned class_num_instance_fields_recursive(Class_Handle ch)
{
assert(ch);
unsigned num_inst_fields = 0;
while(ch) {
num_inst_fields += class_num_instance_fields(ch);
ch = class_get_super_class(ch);
}
return num_inst_fields;
} // class_num_instance_fields_recursive
Field_Handle class_get_field(Class_Handle ch, U_16 idx)
{
assert(ch);
if(idx >= ch->get_number_of_fields()) return NULL;
return ch->get_field(idx);
} // class_get_field
Method_Handle class_get_method_by_name(Class_Handle ch, const char* name)
{
assert(ch);
for(int idx = 0; idx < ch->get_number_of_methods(); idx++) {
Method_Handle meth = ch->get_method(idx);
if(strcmp(meth->get_name()->bytes, name) == 0) {
return meth;
}
}
return NULL;
} // class_get_method_by_name
Field_Handle class_get_field_by_name(Class_Handle ch, const char* name)
{
assert(ch);
for(int idx = 0; idx < ch->get_number_of_fields(); idx++) {
Field_Handle fld = ch->get_field(idx);
if(strcmp(fld->get_name()->bytes, name) == 0) {
return fld;
}
}
return NULL;
} // class_get_field_by_name
Field_Handle class_get_instance_field(Class_Handle ch, unsigned idx)
{
assert(ch);
return ch->get_field(ch->get_number_of_static_fields() + idx);
} // class_get_instance_field
Field_Handle class_get_instance_field_recursive(Class_Handle ch, unsigned idx)
{
assert(ch);
unsigned num_fields_recursive = class_num_instance_fields_recursive(ch);
assert(idx < num_fields_recursive);
while(ch) {
unsigned num_fields = class_num_instance_fields(ch);
unsigned num_inherited_fields = num_fields_recursive - num_fields;
if(idx >= num_inherited_fields) {
Field_Handle fh = class_get_instance_field(ch, idx - num_inherited_fields);
return fh;
}
num_fields_recursive = num_inherited_fields;
ch = class_get_super_class(ch);
}
return 0;
} // class_get_instance_field_recursive
unsigned class_get_number_methods(Class_Handle ch)
{
assert(ch);
return ch->get_number_of_methods();
} // class_get_number_methods
// -gc magic needs this to do the recursive load.
Class_Handle field_get_class_of_field_type(Field_Handle fh)
{
assert(hythread_is_suspend_enabled());
assert(fh);
Class_Handle ch = class_load_class_by_descriptor(field_get_descriptor(fh),
field_get_class(fh));
if(!ch->verify(VM_Global_State::loader_env))
return NULL;
if(!ch->prepare(VM_Global_State::loader_env))
return NULL;
return ch;
} // field_get_class_of_field_type
BOOLEAN field_is_reference(Field_Handle fh)
{
assert((Field *)fh);
Java_Type typ = fh->get_java_type();
return (typ == JAVA_TYPE_CLASS || typ == JAVA_TYPE_ARRAY);
} //field_is_reference
BOOLEAN field_is_magic(Field_Handle fh)
{
assert((Field *)fh);
return fh->is_magic_type();
} //field_is_magic
Boolean field_is_enumerable_reference(Field_Handle fh)
{
assert((Field *)fh);
return ((field_is_reference(fh) && !field_is_magic(fh)));
} //field_is_enumerable_reference
BOOLEAN field_is_injected(Field_Handle f)
{
assert(f);
return f->is_injected();
} //field_is_injected
/////////////////////////////////////////////////////////////////////
// New GC interface demo
// This is just for the purposes of the demo. The GC is free to define
// whatever it wants in this structure, as long as it doesn't exceed the
// size limit. What should the size limit be?
struct GC_VTable {
Class_Handle ch; // for debugging
U_32 num_ref_fields;
U_32 *ref_fields_offsets;
unsigned is_array : 1;
unsigned is_primitive : 1;
};
#define VERBOSE_GC_CLASS_PREPARED 0
/////////////////////////////////////////////////////////////////////
// New signature stuff
Type_Info_Handle method_args_get_type_info(Method_Signature_Handle msh,
unsigned idx)
{
assert(msh);
Method_Signature *ms = (Method_Signature *)msh;
if(idx >= ms->num_args) {
LDIE(70, "Wrong index");
return 0;
}
assert(ms->arg_type_descs);
return ms->arg_type_descs[idx];
} //method_args_get_type_info
Type_Info_Handle method_ret_type_get_type_info(Method_Signature_Handle msh)
{
assert(msh);
Method_Signature *ms = (Method_Signature *)msh;
return ms->return_type_desc;
} //method_ret_type_get_type_info
Type_Info_Handle field_get_type_info(Field_Handle fh)
{
assert(fh);
Field *field = (Field *)fh;
TypeDesc* td = field->get_field_type_desc();
assert(td);
return td;
} // field_get_type_info
/////////////////////////////////////////////////////
// New GC stuff
BOOLEAN class_is_non_ref_array(Class_Handle ch)
{
assert(ch);
// Use the if statement to normalize the value of TRUE
if((ch->get_vtable()->class_properties & CL_PROP_NON_REF_ARRAY_MASK) != 0)
{
assert(ch->is_array());
return TRUE;
} else {
return FALSE;
}
} // class_is_non_ref_array
BOOLEAN class_is_finalizable(Class_Handle ch)
{
assert(ch);
assert(ch->has_finalizer() ==
((ch->get_vtable()->class_properties & CL_PROP_FINALIZABLE_MASK) != 0));
return ch->has_finalizer() ? TRUE : FALSE;
} // class_is_finalizable
WeakReferenceType class_is_reference(Class_Handle clss)
{
assert(clss);
if(class_get_extended_class(clss, "java/lang/ref/WeakReference") != NULL)
return WEAK_REFERENCE;
else if(class_get_extended_class(clss, "java/lang/ref/SoftReference") != NULL)
return SOFT_REFERENCE;
else if(class_get_extended_class(clss, "java/lang/ref/PhantomReference") != NULL)
return PHANTOM_REFERENCE;
else
return NOT_REFERENCE;
}
unsigned class_get_referent_offset(Class_Handle ch)
{
Field_Handle referent =
class_lookup_field_recursive(ch, "referent", "Ljava/lang/Object;");
if (!referent) {
LDIE(6, "Class {0} has no 'Object referent' field" << class_get_name(ch));
}
return referent->get_offset();
}
void* class_alloc_via_classloader(Class_Handle ch, I_32 size)
{
assert(ch);
assert(size >= 0);
Class *clss = (Class *)ch;
assert (clss->get_class_loader());
return clss->get_class_loader()->Alloc(size);
} //class_alloc_via_classloader
unsigned class_get_alignment(Class_Handle ch)
{
assert(ch);
return (unsigned)(ch->get_vtable()->class_properties
& CL_PROP_ALIGNMENT_MASK);
} //class_get_alignment
//
// Returns the size of an element in the array class.
//
unsigned class_element_size(Class_Handle ch)
{
assert(ch);
return ch->get_array_element_size();
} //class_element_size
size_t class_get_object_size(Class_Handle ch)
{
assert(ch);
return ch->get_allocated_size();
} //class_get_object_size
static struct {
const char* c;
const char* m;
const char* d;
} no_inlining_table[] = {
{ "java/lang/ClassLoader", "getCallerClassLoader", "()Ljava/lang/ClassLoader;" },
{ "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;" },
};
static unsigned no_inlining_table_count = sizeof(no_inlining_table)/sizeof(no_inlining_table[0]);
BOOLEAN method_is_no_inlining(Method_Handle mh)
{
assert(mh);
const char* c = class_get_name(method_get_class(mh));
const char* m = method_get_name(mh);
const char* d = method_get_descriptor(mh);
for(unsigned i=0; i<no_inlining_table_count; i++)
if (strcmp(c, no_inlining_table[i].c)==0 &&
strcmp(m, no_inlining_table[i].m)==0 &&
strcmp(d, no_inlining_table[i].d)==0)
return TRUE;
return FALSE;
} // method_is_no_inlining
// Class ch is a subclass of method_get_class(mh). The function returns a method handle
// for an accessible method overriding mh in ch or in its closest superclass that overrides mh.
// Class ch must be a class not an interface.
Method_Handle method_get_overriding_method(Class_Handle ch, Method_Handle mh)
{
assert(ch);
assert(mh);
Method *method = (Method *)mh;
assert(!ch->is_interface()); // ch cannot be an interface
const String *name = method->get_name();
const String *desc = method->get_descriptor();
Method *m = NULL;
for(; ch; ch = ch->get_super_class()) {
m = ch->lookup_method(name, desc);
if (m != NULL) {
// IllegalAccessError will be thrown if implementation of
// interface method is not public
if (method->get_class()->is_interface() && !m->is_public()) {
return NULL;
}
// The method m can only override mh/method
// if m's class can access mh/method (JLS 6.6.5).
if(m->get_class()->can_access_member(method)) {
break;
}
}
}
return m;
} // method_get_overriding_method
I_32 vector_get_length(Vector_Handle vector)
{
assert(vector);
// XXX- need some assert that "vector" is really an array type
return get_vector_length(vector);
} //vector_get_length
Managed_Object_Handle *vector_get_element_address_ref(Vector_Handle vector, I_32 idx)
{
assert(vector);
Managed_Object_Handle *elem = (Managed_Object_Handle *)get_vector_element_address_ref(vector, idx);
return elem;
} //vector_get_element_address_ref
unsigned vm_vector_size(Class_Handle vector_class, int length)
{
assert(vector_class);
return vector_class->calculate_array_size(length);
} // vm_vector_size
static osmutex_t vm_gc_lock;
void vm_gc_lock_init()
{
IDATA UNUSED status = port_mutex_create(&vm_gc_lock, APR_THREAD_MUTEX_NESTED);
assert(status == TM_ERROR_NONE);
} // vm_gc_lock_init
void vm_gc_lock_enum()
{
hythread_t self = tm_self_tls;
int disable_count = self->disable_count;
self->disable_count = 0;
while (true) {
IDATA UNUSED status = port_mutex_lock(&vm_gc_lock);
assert(status == TM_ERROR_NONE);
self->disable_count = disable_count;
if (disable_count && self->suspend_count) {
status = port_mutex_unlock(&vm_gc_lock);
assert(status == TM_ERROR_NONE);
self->disable_count = 0;
hythread_safe_point_other(self);
} else {
break;
}
}
} // vm_gc_lock_enum
void vm_gc_unlock_enum()
{
IDATA UNUSED status = port_mutex_unlock(&vm_gc_lock);
assert(status == TM_ERROR_NONE);
} // vm_gc_unlock_enum
void *vm_get_gc_thread_local()
{
return (void *) &p_TLS_vmthread->_gc_private_information;
}
size_t vm_number_of_gc_bytes_in_vtable()
{
return GC_BYTES_IN_VTABLE;
}
size_t vm_number_of_gc_bytes_in_thread_local()
{
return GC_BYTES_IN_THREAD_LOCAL;
}
BOOLEAN vm_is_heap_compressed()
{
return REFS_IS_COMPRESSED_MODE;
} //vm_is_heap_compressed
void *vm_get_heap_base_address()
{
return (void*)VM_Global_State::loader_env->heap_base;
} //vm_get_heap_base_address
void *vm_get_heap_ceiling_address()
{
return (void *)VM_Global_State::loader_env->heap_end;
} //vm_get_heap_ceiling_address
BOOLEAN vm_is_vtable_compressed()
{
return ManagedObject::are_vtable_pointers_compressed();
} //vm_is_vtable_compressed
Class_Handle allocation_handle_get_class(Allocation_Handle ah)
{
assert(ah);
VTable *vt;
if (vm_is_vtable_compressed())
{
vt = (VTable *) ((UDATA)ah + (UDATA)vm_get_vtable_base_address());
}
else
{
vt = (VTable *) ah;
}
return (Class_Handle) vt->clss;
}
Allocation_Handle class_get_allocation_handle(Class_Handle ch)
{
assert(ch);
return ch->get_allocation_handle();
}
////////////////////////////////////////////////////////////////////////////////////
// Direct call-related functions that allow a JIT to be notified whenever a VM data
// structure changes that would require code patching or recompilation.
////////////////////////////////////////////////////////////////////////////////////
// Called by a JIT in order to be notified whenever the given method is recompiled or
// initially compiled. The callback_data pointer will be passed back to the JIT during the callback.
// The callback method is JIT_recompiled_method_callback.
void vm_register_jit_recompiled_method_callback(JIT_Handle jit, Method_Handle method,
Method_Handle caller,
void *callback_data)
{
assert(method);
assert(caller);
JIT *jit_to_be_notified = (JIT *)jit;
Method *m = (Method *)method;
m->register_jit_recompiled_method_callback(jit_to_be_notified, caller, callback_data);
} //vm_register_jit_recompiled_method_callback
void vm_patch_code_block(U_8* code_block, U_8* new_code, size_t size)
{
assert(code_block != NULL);
assert(new_code != NULL);
// 20030203 We ensure that no thread is executing code that is simultaneously being patched.
// We do this in part by stopping the other threads. This ensures that no thread will try to
// execute code while it is being patched. Also, we take advantage of restrictions on the
// patches done by JIT on IPF: it replaces the branch offset in a single bundle containing
// a branch long. Note that this function does not synchronize the I- or D-caches.
// Run through list of active threads and suspend the other ones.
hythread_suspend_all(NULL, NULL);
patch_code_with_threads_suspended(code_block, new_code, size);
hythread_resume_all(NULL);
} //vm_patch_code_block
// Called by JIT during compilation to have the VM synchronously request a JIT (maybe another one)
// to compile another method.
JIT_Result vm_compile_method(JIT_Handle jit, Method_Handle method)
{
return compile_do_compilation_jit((Method*) method, (JIT*) jit);
} // vm_compile_method
void vm_properties_set_value(const char* key, const char* value, PropertyTable table_number)
{
assert(key);
switch(table_number) {
case JAVA_PROPERTIES:
VM_Global_State::loader_env->JavaProperties()->set(key, value);
break;
case VM_PROPERTIES:
VM_Global_State::loader_env->VmProperties()->set(key, value);
break;
default:
LDIE(71, "Unknown property table: {0}" << table_number);
}
}
char* vm_properties_get_value(const char* key, PropertyTable table_number)
{
assert(key);
char* value;
switch(table_number) {
case JAVA_PROPERTIES:
value = VM_Global_State::loader_env->JavaProperties()->get(key);
break;
case VM_PROPERTIES:
value = VM_Global_State::loader_env->VmProperties()->get(key);
break;
default:
value = NULL;
LDIE(71, "Unknown property table: {0}" << table_number);
}
return value;
}
void vm_properties_destroy_value(char* value)
{
if (value)
{
//FIXME which properties?
VM_Global_State::loader_env->JavaProperties()->destroy(value);
}
}
BOOLEAN vm_property_is_set(const char* key, PropertyTable table_number)
{
bool value = false;
assert(key);
switch(table_number) {
case JAVA_PROPERTIES:
value = VM_Global_State::loader_env->JavaProperties()->is_set(key);
break;
case VM_PROPERTIES:
value = VM_Global_State::loader_env->VmProperties()->is_set(key);
break;
default:
LDIE(71, "Unknown property table: {0}" << table_number);
}
return value ? TRUE : FALSE;
}
char** vm_properties_get_keys(PropertyTable table_number)
{
char** value;
switch(table_number) {
case JAVA_PROPERTIES:
value = VM_Global_State::loader_env->JavaProperties()->get_keys();
break;
case VM_PROPERTIES:
value = VM_Global_State::loader_env->VmProperties()->get_keys();
break;
default:
value = NULL;
LDIE(71, "Unknown property table: {0}" << table_number);
}
return value;
}
char** vm_properties_get_keys_starting_with(const char* prefix, PropertyTable table_number)
{
assert(prefix);
char** value;
switch(table_number) {
case JAVA_PROPERTIES:
value = VM_Global_State::loader_env->JavaProperties()->get_keys_staring_with(prefix);
break;
case VM_PROPERTIES:
value = VM_Global_State::loader_env->VmProperties()->get_keys_staring_with(prefix);
break;
default:
value = NULL;
LDIE(71, "Unknown property table: {0}" << table_number);
}
return value;
}
void vm_properties_destroy_keys(char** keys)
{
if (keys)
{
//FIXME which properties?
VM_Global_State::loader_env->JavaProperties()->destroy(keys);
}
}
int vm_property_get_integer(const char *property_name, int default_value, PropertyTable table_number)
{
assert(property_name);
char *value = vm_properties_get_value(property_name, table_number);
int return_value = default_value;
if (NULL != value)
{
return_value = atoi(value);
vm_properties_destroy_value(value);
}
return return_value;
}
BOOLEAN vm_property_get_boolean(const char *property_name, BOOLEAN default_value, PropertyTable table_number)
{
assert(property_name);
char *value = vm_properties_get_value(property_name, table_number);
if (NULL == value)
{
return default_value;
}
Boolean return_value = default_value;
if (0 == strcmp("no", value)
|| 0 == strcmp("off", value)
|| 0 == strcmp("false", value)
|| 0 == strcmp("0", value))
{
return_value = FALSE;
}
else if (0 == strcmp("yes", value)
|| 0 == strcmp("on", value)
|| 0 == strcmp("true", value)
|| 0 == strcmp("1", value))
{
return_value = TRUE;
}
vm_properties_destroy_value(value);
return return_value;
}
size_t vm_property_get_size(const char *property_name, size_t default_value, PropertyTable table_number)
{
char* size_string;
size_t size;
int sizeModifier;
size_t unit = 1;
size_string = vm_properties_get_value(property_name, table_number);
if (size_string == NULL) {
return default_value;
}
size = atol(size_string);
sizeModifier = tolower(size_string[strlen(size_string) - 1]);
vm_properties_destroy_value(size_string);
switch (sizeModifier) {
case 'k': unit = 1024; break;
case 'm': unit = 1024 * 1024; break;
case 'g': unit = 1024 * 1024 * 1024;break;
}
size_t res = size * unit;
if (res / unit != size) {
/* overflow happened */
return 0;
}
return res;
}
static Annotation* lookup_annotation(AnnotationTable* table, Class* owner, Class* antn_type) {
for (int i = table->length - 1; i >= 0; --i) {
Annotation* antn = table->table[i];
Type_Info_Handle tih = (Type_Info_Handle) type_desc_create_from_java_descriptor(antn->type->bytes, owner->get_class_loader());
if (tih) {
//FIXME optimize: first check if class name matches
Class* type = type_info_get_class(tih);
if (antn_type == type) {
return antn;
}
}
}
TRACE("No such annotation " << antn_type->get_name()->bytes);
return NULL;
}
BOOLEAN method_has_annotation(Method_Handle target, Class_Handle antn_type) {
assert(target);
assert(antn_type);
if (target->get_declared_annotations()) {
Annotation* antn = lookup_annotation(target->get_declared_annotations(), target->get_class(), antn_type);
return antn!=NULL;
}
return false;
}
char * get_method_entry_flag_address()
{
return VM_Global_State::loader_env->TI->get_method_entry_flag_address();
}
char * get_method_exit_flag_address()
{
return VM_Global_State::loader_env->TI->get_method_exit_flag_address();
}