Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 20667 invoked from network); 19 Oct 2005 08:37:27 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 19 Oct 2005 08:37:27 -0000 Received: (qmail 95330 invoked by uid 500); 19 Oct 2005 08:37:17 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 95297 invoked by uid 500); 19 Oct 2005 08:37:17 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 95285 invoked by uid 99); 19 Oct 2005 08:37:17 -0000 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Wed, 19 Oct 2005 01:37:14 -0700 Received: (qmail 20181 invoked by uid 65534); 19 Oct 2005 08:36:54 -0000 Message-ID: <20051019083654.20180.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r326473 [2/2] - /incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/opcode.c Date: Wed, 19 Oct 2005 08:36:53 -0000 To: harmony-commits@incubator.apache.org From: dlydick@apache.org X-Mailer: svnmailer-1.0.5 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Modified: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/opcode.c URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/opcode.c?rev=326473&r1=326472&r2=326473&view=diff ============================================================================== --- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/opcode.c (original) +++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/opcode.c Wed Oct 19 01:36:15 2005 @@ -147,1142 +147,68 @@ * * * - * @todo The code fragment macros used by the opcode switch in - * @link #opcode_run() opcode_run()@endlink need to have the - * local variables documented as to which as required upon - * macro startup and which are set for use at macro completion. + * @todo HARMONY-6-jvm-opcode.c-1 The code fragment macros used by + * the opcode switch in @link #opcode_run() opcode_run()@endlink + * need to have the local variables documented as to which as + * required upon macro startup and which are set for use at + * macro completion. * * * @section Control * - * \$URL$ \$Id$ + * \$URL$ * - * Copyright 2005 The Apache Software Foundation - * or its licensors, as applicable. - * - * Licensed 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. - * - * @version \$LastChangedRevision$ - * - * @date \$LastChangedDate$ - * - * @author \$LastChangedBy$ - * Original code contributed by Daniel Lydick on 09/28/2005. - * - * @section Reference - * - */ - -#include "arch.h" -ARCH_COPYRIGHT_APACHE(opcode, c, "$URL$ $Id$"); - -#include "jvmcfg.h" -#include "cfmacros.h" -#include "classfile.h" -#include "exit.h" -#include "gc.h" -#include "jvm.h" -#include "jvmclass.h" -#include "linkage.h" -#include "method.h" -#include "native.h" -#include "opcode.h" -#include "utf.h" -#include "util.h" - -/*! - * @name Macro support for inner loop opcodes. - * - * @brief Common operations that are used in numerous opcodes - * are gathered here so as to improve accuracy of implementation - * and simplify the code. - * - */ - -/*@{ */ /* Begin grouped definitions */ - -/*! - * @brief Retrieve a two-byte operand that the PC points to. - * - * - * Store thw two-byte operand into the requested @link #u2 u2@endlink - * variable, then increment the program counter to the next byte code - * following it. - * - * @param u2var Name of a @link #u2 u2@endlink variable that will - * receive the two bytes of operand from with the - * instruction. - * - * - * @returns @link #rvoid rvoid@endlink - * - */ -#define GET_U2_OPERAND(u2var) \ - u2var = GETRS2((u2 *) &pcode[pc->offset]); \ - pc->offset += sizeof(u2) - - -/*! - * @name Validate a constant_pool entry - * - */ - - -/*@{ */ /* Begin grouped definitions */ - -/*! - * @brief Check that a constant_pool entry contains - * a specific of tag for this operation. - * - * - * @param u2var Name of a @link #u2 u2@endlink variable that - * contains a constant_pool entry to be examined. - * - * @param cptag1 First constant_pool tag that is valid for this - * operation. - * - * - * @returns @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_VERIFYERROR - * @link #JVMCLASS_JAVA_LANG_VERIFYERROR - if the constant_pool entry does not have the right tag@endlink. - * - */ -#define CHECK_CP_TAG(u2var, cptag1) \ - if (cptag1 != CP_TAG(pcfs, u2var)) \ - { \ - /* Somebody is confused */ \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_VERIFYERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check that a constant_pool entry contains - * the right kind of tag for this operation, from a choice of two. - * - * - * @param u2var Name of a @link #u2 u2@endlink variable that - * contains a constant_pool entry to be examined. - * - * @param cptag1 First constant_pool tag that is valid for this - * operation. - * - * @param cptag2 Second constant_pool tag that is valid for this - * operation. - * - * - * @returns @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_VERIFYERROR - * @link #JVMCLASS_JAVA_LANG_VERIFYERROR - if the constant_pool entry does not have the right tag@endlink. - * - */ -#define CHECK_CP_TAG2(u2var, cptag1, cptag2) \ - if ((cptag1 != CP_TAG(pcfs, u2var)) && \ - (cptag2 != CP_TAG(pcfs, u2var))) \ - { \ - /* Somebody is confused */ \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_VERIFYERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check that a constant_pool entry contains - * the right kind of tag for this operation, from a choice of three. - * - * - * @param u2var Name of a @link #u2 u2@endlink variable that - * contains a constant_pool entry to be examined. - * - * @param cptag1 First constant_pool tag that is valid for this - * operation. - * - * @param cptag2 Second constant_pool tag that is valid for this - * operation. - * - * @param cptag3 Third constant_pool tag that is valid for this - * operation. - * - * - * @returns @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_VERIFYERROR - * @link #JVMCLASS_JAVA_LANG_VERIFYERROR - if the constant_pool entry does not have the right tag@endlink. - * - */ -#define CHECK_CP_TAG3(u2var, cptag1, cptag2, cptag3) \ - if ((cptag1 != CP_TAG(pcfs, u2var)) && \ - (cptag2 != CP_TAG(pcfs, u2var)) && \ - (cptag3 != CP_TAG(pcfs, u2var))) \ - { \ - /* Somebody is confused */ \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_VERIFYERROR); \ -/*NOTREACHED*/ \ - } - -/*@} */ /* End of grouped definitions */ - -/*! - * @brief Force conversion of any Java type variable - * of @c @b sizeof(jint) into a @link #jint jint@endlink - * variable, but without conversion of contents. - * - * - * This macro is typically used to move a - * @link #jvm_object_hash jobject@endlink reference or a - * @link #jfloat jfloat@endlink into a @link #jint jint@endlink - * word, but suppress type conversion between the - * source and destination variables. It derives the - * address of the 32-bit source value, casts it as a - * pointer to the destination data type, then extracts - * that type. - * - * @warning This macro @e must have a 32-bit word as its source. - * For use with smaller types, perform a widening conversion - * first (such as @link #jboolean jboolean@endlink) to - * @link #jint jint@endlink. Then and only then will - * the target type work correctly. - * - * @warning Since this macro takes the address of its source parameter, - * it will only work for variables, not for expressions! - * - * - * @param var_sizeofjint Any 32-bit variable. If it is a smaller - * type, such as (jboolean), perform a - * widening conversion into (jint) first. - * - * @returns (jint) version of @b var_sizeofjint without conversion - * of contents (such as jfloat-to-jint might want to do). - * - * - * @todo A careful review of this macro across different compilers - * is very much in order. - * - */ -#define FORCE_JINT(var_sizeofjint) \ - (*((jint *) ((jvoid *) &var_sizeofjint))) - - -/*! - * @brief Force conversion of any Java type variable - * of @c @b sizeof(jint) into a @link #jfloat jfloat@endlink - * variable, but without conversion of contents. - * - * - * This macro is typically used to move a - * @link #jint jint@endlink into a @link #jint jint@endlink - * word, but suppress type conversion between the - * source and destination variables. - * - * @warning For comments on the dangers of using this macro, - * please refer to @link #FORCE_JINT() FORCE_JINT()@endlink. - * - * - * @param var_sizeofjint Any 32-bit variable. - * - * @returns (jfloat) version of @b var_sizeofjint without conversion - * of contents (such as jint-to-jfloat might want to do). - * - * - * @todo A careful review of this macro across different compilers - * is very much in order. - * - */ -#define FORCE_JFLOAT(var_sizeofjint) \ - (*((jfloat *) ((jvoid *) &var_sizeofjint))) - - -/*! - * @brief Calculate method_info pointer from program counter - * - * During the calculation, various scratch variables are - * loaded and used to simplify the code. The final result - * is a (method_info *) stored the local variable @b pmth - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @returns @link #rvoid rvoid@endlink. - * - */ -#define CALCULATE_METHOD_INFO_FROM_PC \ - clsidxmisc = GET_PC_FIELD_IMMEDIATE(thridx, clsidx); \ - mthidxmisc = GET_PC_FIELD_IMMEDIATE(thridx, mthidx); \ - pcfsmisc = CLASS_OBJECT_LINKAGE(clsidxmisc)->pcfs; \ - pmth = METHOD(clsidxmisc, mthidxmisc) - - -/*! - * @brief Calculate ClassFile pointer from a class reference. - * - * During the calculation, various scratch variables are - * loaded and used to simplify the code. Two final results - * include a (CONSTANT_Class_info *) stored in the local variable - * @b pcpd_Class stored the local variable @b pcfsmisc - * and a (CONSTANT_Class_info *) stored in the local variable - * @b pcpd_Class - * - * @param clsnameidx constant_pool index into class file of current - * class (as indicated in the program counter) - * that is a class reference entry. - * - * - * @returns @link #rvoid rvoid@endlink. - * - * - */ -#define CALCULATE_CLASS_INFO_FROM_CLASS_REFERENCE(clsnameidx) \ - pcpd = pcfs->constant_pool[clsnameidx]; \ - pcpd_Class = PTR_THIS_CP_Class(pcpd); \ - clsidxmisc = pcpd_Class->LOCAL_Class_binding.clsidxJVM; \ - if (jvm_class_index_null == clsidxmisc) \ - { \ - /* Need local variable to avoid possible expansion confusion */\ - jvm_constant_pool_index cpidxOLD = clsnameidx; \ - \ - /* If class is not loaded, go retrieve it by UTF8 class name */\ - LATE_CLASS_LOAD(cpidxOLD); \ - } \ - pcfsmisc = CLASS_OBJECT_LINKAGE(clsidxmisc)->pcfs; /* Extra ; */ - - -/*! - * @brief Attempt to load a class that is not currently loaded. - * - * - * @param clsnameidx CONSTANT_Utf8_info constant_pool index - * to class name - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_NOCLASSDEFFOUNDERROR - * @link #JVMCLASS_JAVA_LANG_NOCLASSDEFFOUNDERROR - if requested class cannot be located@endlink. - * - */ -#define LATE_CLASS_LOAD(clsnameidx) \ - \ - pcpd = pcfs->constant_pool[clsnameidx]; /* Class name */ \ - pcpd_Class = PTR_THIS_CP_Class(pcpd); \ - /* UTF8 string */ \ - pcpd = pcfs->constant_pool[pcpd_Class->name_index]; \ - pcpd_Utf8 = PTR_THIS_CP_Utf8(pcpd); \ - \ - prchar_clsname = utf_utf2prchar(pcpd_Utf8); \ - \ - /* Try again to load class */ \ - clsidxmisc = class_load_resolve_clinit(prchar_clsname, \ - CURRENT_THREAD, \ - rfalse, \ - rfalse); \ - \ - HEAP_FREE_DATA(prchar_clsname); \ - \ - /* If class is irretrievable, abort */ \ - if (jvm_class_index_null == clsidxmisc) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_NOCLASSDEFFOUNDERROR); \ -/*NOTREACHED*/ \ - } - - - - -/*! - * @brief Calculate method_info pointer from a method reference. - * - * During the calculation, various scratch variables are - * loaded and used to simplify the code. Two final results - * include a (method_info *) stored the local variable @b pmth - * and a (CONSTANT_Methodref_info *) stored in the local variable - * @b pcpd_Methodref - * - * @param Methodref constant_pool index into class file of current - * class (as indicated in the program counter) that - * is a method reference entry. - * - * - * @returns @link #rvoid rvoid@endlink. - * - * - * @throws JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR - * @link #JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR - if requested method is not found in the class@endlink. - * - * - */ -#define CALCULATE_METHOD_INFO_FROM_METHOD_REFERENCE(Methodref) \ - pcpd = pcfs->constant_pool[Methodref]; \ - pcpd_Methodref = PTR_THIS_CP_Methodref(pcpd); \ - clsidxmisc = pcpd_Methodref->LOCAL_Methodref_binding.clsidxJVM;\ - if (jvm_class_index_null == clsidxmisc) \ - { \ - /* If class is not loaded, go retrieve it by UTF8 class name */\ - LATE_CLASS_LOAD(pcpd_Methodref->class_index); \ - \ - /* Check if method exists in loaded class */ \ - clsidxmisc = pcpd_Methodref->LOCAL_Methodref_binding.clsidxJVM;\ - if (jvm_class_index_null == clsidxmisc) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR); \ -/*NOTREACHED*/ \ - } \ - } \ - \ - mthidxmisc = pcpd_Methodref->LOCAL_Methodref_binding.mthidxJVM; \ - if (jvm_method_index_bad == mthidxmisc) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR); \ -/*NOTREACHED*/ \ - } \ - \ - pcfsmisc = CLASS_OBJECT_LINKAGE(clsidxmisc)->pcfs; \ - pmth = pcfsmisc->methods[mthidxmisc] - - -/*! - * @brief Check for code attribute index in local method binding. - * - * - * @param codeatridx Code attribute index from a local method binding - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR - * @link #JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR - if requested class static field is not found in the class@endlink. - * - */ -#define CHECK_VALID_CODEATRIDX(codeatridx) \ - if (jvm_attribute_index_bad == codeatridx) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this method is a static method. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_VERIFYERROR - * @link #JVMCLASS_JAVA_LANG_VERIFYERROR - if requested method is an object instance method@endlink. - * - */ -#define CHECK_STATIC_METHOD \ - \ - /* Must be a static method */ \ - if (!(ACC_STATIC & pmth->access_flags)) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_VERIFYERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this method is an object instance method. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_VERIFYERROR - * @link #JVMCLASS_JAVA_LANG_VERIFYERROR - if requested method is a static method@endlink. - * - */ -#define CHECK_INSTANCE_METHOD \ - \ - /* Must be an instance method */ \ - if (ACC_STATIC & pmth->access_flags) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_VERIFYERROR); \ -/*NOTREACHED*/ \ - } - - -#if 0 -/*! - * @brief Check if this method is an @c @b abstract method, - * that is, not having a concrete implementation. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - * @link #JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - if requested method is a method with a concrete implementatino@endlink. - * - */ -#define CHECK_ABSTRACT_METHOD \ - \ - /* Must not be a concrete method */ \ - if (!(ACC_ABSTRACT & pmth->access_flags)) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ -\ -/* What exception gets thrown here? Need "not" of InstantiationError */\ -\ - JVMCLASS_JAVA_LANG_INSTANTIATIONERROR); \ -/*NOTREACHED*/ \ - } -#endif - - -/*! - * @brief Check if this method is a concrete method, that is, - * not @c @b abstract . - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - * @link #JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - if requested method is an abstract method@endlink. - * - */ -#define CHECK_NOT_ABSTRACT_METHOD \ - \ - /* Must not be an abstract method */ \ - if (ACC_ABSTRACT & pmth->access_flags) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_INSTANTIATIONERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this object is from a concrete class, that is, - * not from an @c @b abstract class. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - * @link #JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - if requested object is an abstract object@endlink. - * - */ -#define CHECK_NOT_ABSTRACT_CLASS \ - \ - /* Must not be from an abstract class */ \ - if (ACC_ABSTRACT & \ - OBJECT_CLASS_LINKAGE(objhashmisc)->pcfs->access_flags) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_INSTANTIATIONERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this object is a scalar, that is, not an array. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - * @link #JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - if requested method is an array object@endlink. - * - */ -#define CHECK_NOT_ARRAY_OBJECT \ - \ - /* Must not be an array object */ \ - if (OBJECT_STATUS_ARRAY & \ - CLASS(OBJECT_CLASS_LINKAGE(objhashmisc)->clsidx).status) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_INSTANTIATIONERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this object is from a normal class, that is, - * not from an interface class. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - * @link #JVMCLASS_JAVA_LANG_INSTANTIATIONERROR - if requested object is from an interface class@endlink. - * - */ -#define CHECK_NOT_INTERFACE_CLASS \ - \ - /* Must not be from an interface class */ \ - if (ACC_INTERFACE & \ - OBJECT_CLASS_LINKAGE(objhashmisc)->pcfs->access_flags) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_INSTANTIATIONERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Calculate field_info pointer from a field reference. - * - * During the calculation, various scratch variables are - * loaded and used to simplify the code. Two final results - * include a (field_info *) stored the local variable @b pfld - * and a (CONSTANT_Fieldref_info *) stored in the local variable - * @b pcpd_Fieldref - * - * @param Fieldref constant_pool index into class file of current - * class (as indicated in the program counter) that - * is a method reference entry. - * - * - * @returns @link #rvoid rvoid@endlink. - * - * - * @throws JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR - * @link #JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR - if requested field is not found in the class@endlink. - * - */ -#define CALCULATE_FIELD_INFO_FROM_FIELD_REFERENCE(Fieldref) \ - pcpd = pcfs->constant_pool[Fieldref]; \ - pcpd_Fieldref = PTR_THIS_CP_Fieldref(pcpd); \ - clsidxmisc = pcpd_Fieldref->LOCAL_Fieldref_binding.clsidxJVM; \ - if (jvm_class_index_null == clsidxmisc) \ - { \ - /* If class is not loaded, go retrieve it by UTF8 class name */\ - LATE_CLASS_LOAD(pcpd_Fieldref->class_index); \ - \ - /* Check if field exists in loaded class */ \ - clsidxmisc = pcpd_Fieldref->LOCAL_Fieldref_binding.clsidxJVM; \ - if (jvm_class_index_null == clsidxmisc) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR); \ -/*NOTREACHED*/ \ - } \ - } \ - \ - fluidxmisc = pcpd_Fieldref->LOCAL_Fieldref_binding.fluidxJVM; \ - if (jvm_field_index_bad == fluidxmisc) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR); \ -/*NOTREACHED*/ \ - } \ - \ - pcfsmisc = CLASS_OBJECT_LINKAGE(clsidxmisc)->pcfs; \ - fluidxmisc = pcpd_Fieldref->LOCAL_Fieldref_binding.fluidxJVM; \ - pfld = pcfsmisc \ - ->fields[CLASS(clsidxmisc) \ - .class_static_field_lookup[fluidxmisc]] - - -/*! - * @brief Check for field lookup index in local field binding. - * - * - * @param fluidx Field lookup index from a local field binding - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR - * @link #JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR - if requested class static field is not found in the class@endlink. - * - */ -#define CHECK_VALID_FIELDLOOKUPIDX(fluidx) \ - if (jvm_field_lookup_index_bad == fluidx) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this field is a static field. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR - * @link #JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR - if requested field is an object instance field@endlink. - * - */ -#define CHECK_STATIC_FIELD \ - \ - /* Must be a static field */ \ - if (!(ACC_STATIC & pfld->access_flags)) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this field is an object instance field. - * - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR - * @link #JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR - if requested method is a static field@endlink. - * - */ -#define CHECK_INSTANCE_FIELD \ - \ - /* Must be an instance field */ \ - if (ACC_STATIC & pfld->access_flags) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_INCOMPATIBLECLASSCHANGEERROR); \ -/*NOTREACHED*/ \ - } - - -/*! - * @brief Check if this field is a final field in the current class. - * - * - * Determine if a final field is in the current class. If so, fine, - * but otherwise it is in a superclass. This is an error. - * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @return @link #rvoid rvoid@endlink - * - * - * @throws JVMCLASS_JAVA_LANG_ILLEGALACCESSERROR - * @link #JVMCLASS_JAVA_LANG_ILLEGALACCESSERROR - if requested field is final, but in a superclass@endlink. - * - */ -#define CHECK_FINAL_FIELD_CURRENT_CLASS \ - \ - { \ - jvm_class_index clsidxTMP; \ - \ - GET_PC_FIELD(thridx, clsidxTMP, clsidx); \ - \ - /* A final field must _not_ be found in a superclass */ \ - if ((ACC_FINAL & pfld->access_flags) && \ - (clsidxTMP != pcpd_Fieldref \ - ->LOCAL_Fieldref_binding.clsidxJVM)) \ - { \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_ILLEGALACCESSERROR); \ -/*NOTREACHED*/ \ - } \ - } - - -/*! - * @brief Check if this field requires two @link #jint jint@endlink - * accesses or just one. - * - * - * JVM stack operations and local variable accesses need to know - * if the datum to be moved takes one @link #jint jint@endlink slot - * or two. Items of types @link #jlong jlong@endlink and - * @link #jdouble jdouble@endlink take two such accesses, all others - * take just one. + * \$Id$ * - * @b Parameters: @link #rvoid rvoid@endlink - * - * - * @returns @link #rtrue rtrue@endlink if this field takes two - * accesses, otherwise @link #rfalse rfalse@endlink for smaller types. - * - */ -#define CHECK_TWO_ACCESSES \ - \ - (((pcpd_Fieldref->LOCAL_Fieldref_binding.jvaluetypeJVM == \ - BASETYPE_CHAR_J) || \ - (pcpd_Fieldref->LOCAL_Fieldref_binding.jvaluetypeJVM == \ - BASETYPE_CHAR_D)) \ - ? rtrue \ - : rfalse) - - -/*! - * @brief Store out value by data type into either class static field - * or object instance field. - * - * - * @param data_array Expression pointing to the class' or object's - * @b XXX_data[] array, namely a (jvalue *). - * Typically a fixed set of two expressions. - * - * - * @returns @link #rvoid rvoid@endlink - * - * - * @see PUTFIELD - * - * @see PUTSTATIC - * - * - * @todo The various type casting games of integer/sub-integer - * and integer/float/double and integer/objhash need to be - * carefully scrutinized for correctness at run time. - * - * @todo Is BASTYPE_CHAR_ARRAY a legal case for @b PUTSTATIC and - * @b PUTFIELD ? - * - */ -#define PUTDATA(data_array) \ - switch (pcpd_Fieldref->LOCAL_Fieldref_binding.jvaluetypeJVM) \ - { \ - case BASETYPE_CHAR_B: \ - POP(thridx, \ - data_array._jbyte, \ - jbyte); \ - break; \ - \ - case BASETYPE_CHAR_C: \ - POP(thridx, \ - data_array._jchar, \ - jchar); \ - break; \ - \ - case BASETYPE_CHAR_D: \ - /* \ - * DO NOT pop into a 64-bit word! @link #POP() POP@endlink\ - * was only designed to operate on 32-bit data types. \ - * Instead, use two instances. Besides, these halves \ - * needs to get pushed through bytegames_combine_jdouble() \ - * anyway to retrieve the final \ - * @link #jdouble jdouble@endlink value. \ - */ \ - POP(thridx, jitmp2, jint); \ - POP(thridx, jitmp1, jint); \ - data_array._jdouble = bytegames_combine_jdouble(jitmp1, \ - jitmp2); \ - break; \ - \ - case BASETYPE_CHAR_F: \ - /* \ - * DO NOT pop into a jfloat! This will consider \ - * the source as an integer to be converted instead \ - * of a 32-bit floating point word stored in a 32-bit \ - * integer word on the stack. Instead, use the \ - * FORCE_JFLOAT() macro to sustain contents across \ - * type boundaries. \ - */ \ - POP(thridx, jitmp1, jint); \ - data_array._jfloat = FORCE_JFLOAT(jitmp1); \ - break; \ - \ - case BASETYPE_CHAR_I: \ - POP(thridx, \ - data_array._jint, \ - /* redundant: */ jint); \ - break; \ - \ - case BASETYPE_CHAR_J: \ - /* \ - * DO NOT pop into a 64-bit word! @link #POP() POP@endlink\ - * was only designed to operate on 32-bit data types. \ - * Instead, use two instances. Besides, these halves \ - * needs to get pushed through bytegames_combine_jlong() \ - * anyway to retrieve the final \ - * @link #jlong jlong@endlink value. \ - */ \ - POP(thridx, jitmp2, jint); \ - POP(thridx, jitmp1, jint); \ - jltmp = bytegames_combine_jlong(jitmp1, jitmp2); \ - data_array._jlong = jltmp; \ - break; \ - \ - case BASETYPE_CHAR_L: \ - POP(thridx, \ - data_array._jobjhash, \ - jvm_object_hash); \ - break; \ - \ - case BASETYPE_CHAR_S: \ - POP(thridx, \ - data_array._jshort, \ - jshort); \ - break; \ - \ - case BASETYPE_CHAR_Z: \ - POP(thridx, \ - data_array._jboolean, \ - jboolean); \ - break; \ - \ - case BASETYPE_CHAR_ARRAY: \ - POP(thridx, \ - data_array._jarray, \ - jvm_object_hash); \ - break; \ - \ - case LOCAL_BASETYPE_ERROR: \ - default: \ - /* Something is @e very wrong if code gets here */ \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_VERIFYERROR); \ -/*NOTREACHED*/ \ - break; \ - } - - -/*! - * @brief Store out value by data type into class static field. - * - */ -#define PUTSTATIC \ - PUTDATA(CLASS(pcpd_Fieldref->LOCAL_Fieldref_binding.clsidxJVM) \ - .class_static_field_data[fluidxmisc]) - - -/*! - * @brief Store out value by data type into object instance field. - * - */ -#define PUTFIELD \ - PUTDATA(OBJECT(pcpd_Fieldref->LOCAL_Fieldref_binding.clsidxJVM) \ - .object_instance_field_data[fluidxmisc]) - - -/*! - * @brief Retrieve value by data type from either class static field or - * object instance field. - * - * - * @param data_array Expression pointing to the class' or object's - * @b XXX_data[] array, namely a (jvalue *). - * Typically a fixed set of two expressions. - * - * - * @returns @link #rvoid rvoid@endlink - * - * - * @see GETFIELD - * - * @see GETSTATIC + * Copyright 2005 The Apache Software Foundation + * or its licensors, as applicable. + * + * Licensed 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. * + * @version \$LastChangedRevision$ * - * @todo The various type casting games of integer/sub-integer - * and integer/float/double and integer/objhash need to be - * carefully scrutinized for correctness at run time. + * @date \$LastChangedDate$ * - * @todo Is BASTYPE_CHAR_ARRAY a legal case for @b GETSTATIC and - * @b GETFIELD ? + * @author \$LastChangedBy$ * - */ -#define GETDATA(data_array) \ - switch (pcpd_Fieldref->LOCAL_Fieldref_binding.jvaluetypeJVM) \ - { \ - case BASETYPE_CHAR_B: \ - PUSH(thridx, \ - (jint) data_array._jbyte); \ - break; \ - \ - case BASETYPE_CHAR_C: \ - PUSH(thridx, \ - (jint) data_array._jchar); \ - break; \ - \ - case BASETYPE_CHAR_D: \ - bytegames_split_jdouble(data_array._jdouble, \ - &jitmp1, \ - &jitmp2); \ - /* \ - * DO NOT push from a 64-bit word! @link #PUSH() \ - PUSH@endlink was only designed to operate on 32-bit \ - * data types. Instead, use two instances. \ - */ \ - PUSH(thridx, jitmp1); \ - PUSH(thridx, jitmp2); \ - break; \ - \ - case BASETYPE_CHAR_F: \ - /* \ - * DO NOT pop into a jfloat! This will consider \ - * the source as an integer to be converted instead \ - * of a 32-bit floating point word stored in a 32-bit \ - * integer word on the stack. Instead, use the \ - * FORCE_JFLOAT() macro to sustain contents across \ - * type boundaries. \ - */ \ - jitmp1 = FORCE_JINT(data_array._jfloat); \ - PUSH(thridx, jitmp1); \ - break; \ - \ - case BASETYPE_CHAR_I: \ - PUSH(thridx, \ - (jint) /* ... redundant */ data_array._jint); \ - break; \ - \ - case BASETYPE_CHAR_J: \ - bytegames_split_jlong(data_array._jlong, \ - &jitmp1, \ - &jitmp2); \ - /* \ - * DO NOT push from a 64-bit word! @link #PUSH() \ - PUSH@endlink was only designed to operate on 32-bit \ - * data types. Instead, use two instances. \ - */ \ - PUSH(thridx, jitmp1); \ - PUSH(thridx, jitmp2); \ - break; \ - \ - case BASETYPE_CHAR_L: \ - PUSH(thridx, \ - (jint) data_array._jobjhash); \ - break; \ - \ - case BASETYPE_CHAR_S: \ - PUSH(thridx, \ - (jint) data_array._jshort); \ - break; \ - \ - case BASETYPE_CHAR_Z: \ - PUSH(thridx, \ - (jint) data_array._jboolean); \ - break; \ - \ - case BASETYPE_CHAR_ARRAY: \ - PUSH(thridx, \ - (jint) data_array._jarray); \ - break; \ - \ - case LOCAL_BASETYPE_ERROR: \ - default: \ - /* Something is @e very wrong if code gets here */ \ - thread_throw_exception(thridx, \ - THREAD_STATUS_THREW_ERROR, \ - JVMCLASS_JAVA_LANG_VERIFYERROR); \ -/*NOTREACHED*/ \ - break; \ - } - - -/*! - * @brief Retrieve value by data type from class static field. + * Original code contributed by Daniel Lydick on 09/28/2005. * - */ -#define GETSTATIC \ - GETDATA(CLASS(pcpd_Fieldref->LOCAL_Fieldref_binding.clsidxJVM) \ - .class_static_field_data[fluidxmisc]) - - -/*! - * @brief Retrieve value by data type from object instance field. + * @section Reference * */ -#define GETFIELD \ - GETDATA(OBJECT(pcpd_Fieldref->LOCAL_Fieldref_binding.clsidxJVM) \ - .object_instance_field_data[fluidxmisc]) +#include "arch.h" +ARCH_SOURCE_COPYRIGHT_APACHE(opcode, c, +"$URL$", +"$Id$"); -/*@} */ /* End of grouped definitions */ - -/*! - * Handler linkage for end of thread detection. - */ -static jmp_buf opcode_end_thread_return; +#define PORTABLE_JMP_BUF_VISIBLE +#include "jvmcfg.h" +#include "cfmacros.h" +#include "classfile.h" +#include "exit.h" +#include "gc.h" +#include "jvm.h" +#include "jvmclass.h" +#include "linkage.h" +#include "method.h" +#include "native.h" +#include "opcode.h" +#include "opmacros.h" +#include "utf.h" +#include "util.h" /*! @@ -1294,7 +220,7 @@ * inner @c @b while() loop when a thread has finished * running. * - * @b Parameters: @link #rvoid rvoid@endlink + * @param penv Non-local return buffer for use by @c @b setjmp(3) call. * * * @returns From normal setup, integer @@ -1304,18 +230,13 @@ * from @link #opcode_end_thread_test() opcode_end_thread_test()@endlink. * + * @attention See comments in @link jvm/src/portable_jmp_buf.c + portable_jmp_buf.c@endlink as to why this @e cannot + * be a function call. + * */ -static int opcode_end_thread_setup(rvoid) -{ - /* - * Return point from @c @b longjmp(3) as declared - * in @link #opcode_end_thread_test() - opcode_end_thread_test()@endlink - */ - return(setjmp(opcode_end_thread_return)); - -} /* END of opcode_end_thread_setup() */ +#define OPCODE_END_THREAD_SETUP(penv) PORTABLE_SETJMP(penv) /*! @@ -1335,18 +256,24 @@ * state and a non-local return exits the while loop. * * - * @param thridx Thread index of thread to evaluate. + * @param thridx Thread index of thread to evaluate + * + * @param penv Non-local return buffer for use by @c @b longjmp(3) + * call. * * * @returns @link #rvoid rvoid@endlink if end of thread test fails. * If test passes, perform non-local state restoration from - * setup via @c @b setjmp(3) as stored in @link - #opcode_end_thread_return opcode_end_thread_return@endlink. + * setup via @c @b setjmp(3) as stored in a local variable + * in @link #opcode_run() opcode_run()@endlink. * */ -static rvoid opcode_end_thread_test(jvm_thread_index thridx) +static rvoid opcode_end_thread_test(jvm_thread_index thridx, + portable_jmp_buf *penv) { + ARCH_FUNCTION_NAME(opcode_end_thread_test); + /* Check if thread has finished running */ /*! @@ -1354,8 +281,8 @@ * something like a @c @b \ or @c @b \ was loaded * on top of a running program. * - * @todo Should FP condition be fp_end_program <= THREAD().fp - * instead of < condition? + * @todo HARMONY-6-jvm-opcode.c-2 Should FP condition be + * fp_end_program <= THREAD().fp instead of < condition? * */ if (THREAD(thridx).fp_end_program < THREAD(thridx).fp) @@ -1367,7 +294,9 @@ /* Thread has finished running, so return to @c @b setjmp(3) */ int rc = (int) EXIT_JVM_THREAD; - longjmp(opcode_end_thread_return, rc); + + PORTABLE_LONGJMP(penv, rc); + /*NOTREACHED*/ } /* END of opcode_end_thread_test() */ @@ -1401,45 +330,49 @@ * @link #JVMCLASS_JAVA_LANG_ERROR JVMCLASS_JAVA_LANG_ERROR@endlink. * Anything else will produce undefined results. * - * @warning This handler is not a simple as it seems! You - * absolutely @e must know what the non-local return mechanism - * @c @b setjmp(3)/longjmp(3) is before attempting to figure it out!!! - * - * The strategy is a simple one: Trap thrown errors by this handler - * and trap a failure in that error class by throwing a @link - #JVMCLASS_JAVA_LANG_INTERNALERROR - JVMCLASS_JAVA_LANG_INTERNALERROR@endlink. If that fails, give up. - * - * @b Details: When this function is first called due to a thrown - * error, it attempts to load and run that error class. If all - * is well, that class runs and everyone lives happily ever after. - * If that class throws an error, however, this handler, having - * been re-armed, is activated semi-recursively via @link - #exit_throw_exception() exit_throw_exception()@endlink, - * (that is, not entering at the top of function, but at the return - * from @link #exit_throw_exception() exit_throw_exception()@endlink - * with a non-zero return value), entering @e this code at - * @link #exit_exception_setup exit_exception_setup()@endlink, - * choosing the conditional branch != @link #EXIT_MAIN_OKAY - EXIT_MAIN_OKAY@endlink and attempts to recursively load and - * run @link #JVMCLASS_JAVA_LANG_LINKAGEERROR - JVMCLASS_JAVA_LANG_LINKAGEERROR@endlink. If this is successful, - * fine, call @link #exit_jvm() exit_jvm()@endlink and be done. - * However, if even @e this fails and throws an error, the handler, - * having been rearmed @e again by the attempt to invoke - * @link #JVMCLASS_JAVA_LANG_LINKAGEERROR - JVMCLASS_JAVA_LANG_LINKAGEERROR@endlink, it again semi-recursively - * is activated via @link #exit_throw_exception() - exit_throw_exception()@endlink and again enters the code at - * @link #exit_exception_setup() exit_exception_setup()@endlink. This - * time, the global - * @link #opcode_calling_java_lang_linkageerror - opcode_calling_java_lang_linkageerror@endlink is - * @link #rtrue rtrue@endlink, so no more recursive invocations - * are performed. Instead, @link #exit_jvm() exit_jvm()@endlink - * with the most recent @link #EXIT_MAIN_OKAY EXIT_xxx@endlink code - * from @link #exit_throw_exception() exit_throw_exception()@endlink - * and be done. + * @warning This handler is not a simple as it seems! + * You absolutely @e must know what the non-local return + * mechanism @c @b setjmp(3)/longjmp(3) is before attempting + * to figure it out!!! + * + * The strategy is a simple one: Trap thrown errors by this + * handler and trap a failure in that error class by throwing + * a @link #JVMCLASS_JAVA_LANG_INTERNALERROR + JVMCLASS_JAVA_LANG_INTERNALERROR@endlink. If that fails, + * give up. + * + * @b Details: When this function is first called due to a + * thrown error, it attempts to load and run that error class. + * If all is well, that class runs and everyone lives happily + * ever after. If that class throws an error, however, this + * handler, having been re-armed, is activated semi-recursively + * via @link #exit_throw_exception() + exit_throw_exception()@endlink, (that is, not entering at + * the top of function, but at the return from + * @link #exit_throw_exception() exit_throw_exception()@endlink + * with a non-zero return value), entering @e this code at + * @link #exit_exception_setup exit_exception_setup()@endlink, + * choosing the conditional branch != @link #EXIT_MAIN_OKAY + EXIT_MAIN_OKAY@endlink and attempts to recursively load and + * run @link #JVMCLASS_JAVA_LANG_LINKAGEERROR + JVMCLASS_JAVA_LANG_LINKAGEERROR@endlink. If this is + * successful, fine, call @link #exit_jvm() exit_jvm()@endlink + * and be done. However, if even @e this fails and throws an + * error, the handler, having been rearmed @e again by the + * attempt to invoke @link #JVMCLASS_JAVA_LANG_LINKAGEERROR + JVMCLASS_JAVA_LANG_LINKAGEERROR@endlink, it again + * semi-recursively is activated via + * @link #exit_throw_exception() exit_throw_exception()@endlink + * and again enters the code at @link #exit_exception_setup() + exit_exception_setup()@endlink. This time, the global + * @link #opcode_calling_java_lang_linkageerror + opcode_calling_java_lang_linkageerror@endlink is + * @link #rtrue rtrue@endlink, so no more recursive invocations + * are performed. Instead, @link #exit_jvm() + exit_jvm()@endlink with the most recent + * @link #EXIT_MAIN_OKAY EXIT_xxx@endlink code from + * @link #exit_throw_exception() exit_throw_exception()@endlink + * and be done. * * * @param pThrowableEvent Null-terminated string name of @@ -1450,42 +383,46 @@ * into. * * - * @returns @link #rvoid rvoid@endlink. Either the - * @c @b java.lang.Throwable class loads and - * runs, or it loads @c @b java.lang.LinkageError - * and runs it, then returns to caller, or it exits - * due to an error somewhere in this sequence of - * events. + * @returns @link #rvoid rvoid@endlink. Either the + * @c @b java.lang.Throwable class loads and + * runs, or it loads @c @b java.lang.LinkageError + * and runs it, then returns to caller, or it exits + * due to an error somewhere in this sequence of + * events. * */ rvoid opcode_load_run_throwable(rchar *pThrowableEvent, jvm_thread_index thridx) { + ARCH_FUNCTION_NAME(opcode_load_run_throwable); + /******* Re-arm java.lang.LinkageError handler ***/ /*! * @internal This call to exit_exception_setup() and the following - * if (@link #EXIT_MAIN_OKAY EXIT_MAIN_OKAY@endlink) statement - * constitute the ugly part of this code as described above. - * See also other recursive calls and their control via - * @link #opcode_calling_java_lang_linkageerror - opcode_calling_java_lang_linkageerror@endlink: + * if (@link #EXIT_MAIN_OKAY EXIT_MAIN_OKAY@endlink) + * statement constitute the ugly part of this code as + * described above. See also other recursive calls and + * their control via @link + #opcode_calling_java_lang_linkageerror + opcode_calling_java_lang_linkageerror@endlink: * */ - int nonlocal_rc = exit_exception_setup(); + exit_exception_setup(); + int nonlocal_rc = EXIT_EXCEPTION_SETUP(); if (EXIT_MAIN_OKAY != nonlocal_rc) { /*! - * @todo Make this load and run the error class - * @c @b \ and default @c @b \ method - * instead of/in addition to fprintf(). Other - * exit_throw_exception() handlers will have invoked - * this method, so it @e must be rearmed @e again at - * this point, lest an error that invokes it causes - * an infinite loop. + * @todo HARMONY-6-jvm-opcode.c-3 Make this load and run + * the error class @c @b \ and default + * @c @b \ method instead of/in addition to + * fprintf(). Other exit_throw_exception() handlers + * will have invoked this method, so it @e must be + * rearmed @e again at this point, lest an error + * that invokes it causes an infinite loop. */ /* Should never be true via exit_throw_exception() */ @@ -1521,7 +458,7 @@ if (jvm_thread_index_null == thridx) { - sysErrMsg("opcode_load_run_throwable", + sysErrMsg(arch_function_name, "Invalid thread index %d for throwable class %s", thridx, pThrowableEvent); return; @@ -1542,16 +479,16 @@ /*! * @internal Both mark (here) and unmark (below) class - * so it gets garbage collected. + * so it gets garbage collected. */ (rvoid) GC_CLASS_MKREF_FROM_CLASS(jvm_class_index_null, clsidx); /*! * @internal Instantiate error class object and run its default - * @c @b \ method with default parameters. + * @c @b \ method with default parameters. * - * If an error is thrown in objec_instance_new(), re-enter this + * If an error is thrown in object_instance_new(), re-enter this * error function recursively at exit_exception_setup(). */ jvm_object_hash objhash= @@ -1565,14 +502,14 @@ /*! * @internal Both mark and unmark object so it - * gets garbage collected + * gets garbage collected */ (rvoid) GC_OBJECT_MKREF_FROM_OBJECT(jvm_object_hash_null, objhash); (rvoid) GC_OBJECT_RMREF_FROM_OBJECT(jvm_object_hash_null, objhash); /*! * @internal Unmarked from above-- since JVM is going down, - * this may be irrelevant, but be consistent. + * this may be irrelevant, but be consistent. */ (rvoid) GC_CLASS_RMREF_FROM_CLASS(jvm_class_index_null, clsidx); @@ -1602,12 +539,14 @@ * may be found in object_run_method() as far as initiating execution * of a JVM method. * - * @todo See if there is a better time-slicing algorithm that - * is just as easy to use and keeps good real clock time. + * @todo HARMONY-6-jvm-opcode.c-4 See if there is a better + * time-slicing algorithm that is just as easy to use + * and keeps good real clock time. * - * @todo: having @c @b run_init_ (parm 7) for invocations of - * opject_instance_new() to be @link #rfalse rfalse@endlink - * the right thing to do for array initialization, namely + * @todo: HARMONY-6-jvm-opcode.c-5 having @c @b run_init_ (parm 6) + * for invocations of opject_instance_new() to be + * @link #rfalse rfalse@endlink the right thing to + * do for array initialization, namely * opcodes @b NEWARRAY and @b ANEWARRAY ? Initializing an * array is really not a constructor type * of operation, but the individual components @@ -1634,6 +573,18 @@ rboolean opcode_run(jvm_thread_index thridx, rboolean check_timeslice) { + ARCH_FUNCTION_NAME(opcode_run); + + /*! + * @internal Handler linkage for end of thread detection. + * This structure is @e horrible. It is @e ugly. See + * @link jvm/src/portable_jmp_buf.c portable_jmp_buf.c@endlink + * for other hazards and rationale for workaround. + * + */ + portable_jmp_buf opcode_end_thread_nonlocal_return; + + /* * Arm handler for the three conditions * java.lang.Error, Exception, and Throwable. @@ -1643,7 +594,7 @@ * handler in the class will issue: * * - longjmp(THREAD(thridx).nonlocal_ThrowableEvent, rc) +PORTABLE_LONGJMP(THREAD(thridx).pportable_nonlocal_ThrowableEvent, rc) * * by way of @link #thread_throw_exception() @@ -1659,7 +610,8 @@ int nonlocal_thread_return = EXIT_JVM_INTERNAL; /* Calls @c @b setjmp(3) to arm handler */ - int nonlocal_rc = thread_exception_setup(thridx); + thread_exception_setup(thridx); + int nonlocal_rc = THREAD_EXCEPTION_SETUP(thridx); /* Show error case first due to @e long switch() following */ if (THREAD_STATUS_EMPTY != nonlocal_rc) @@ -1696,17 +648,23 @@ */ if (THREAD_STATUS_THREW_EXCEPTION & nonlocal_rc) { - /*! @todo What needs to go here? */ + /*! + * @todo HARMONY-6-jvm-opcode.c-6 What needs to go here? + */ } else if (THREAD_STATUS_THREW_ERROR & nonlocal_rc) { - /*! @todo What needs to go here? */ + /*! + * @todo HARMONY-6-jvm-opcode.c-7 What needs to go here? + */ } else if (THREAD_STATUS_THREW_THROWABLE & nonlocal_rc) { - /*! @todo What needs to go here? */ + /*! + * @todo HARMONY-6-jvm-opcode.c-8 What needs to go here? + */ } else if (THREAD_STATUS_THREW_UNCAUGHT & nonlocal_rc) @@ -1723,7 +681,7 @@ if (jvm_class_index_null == clsidx) { /* Problem creating error class, so quit */ - sysErrMsg("opcode_run", + sysErrMsg(arch_function_name, "Cannot find class %s", JVMCLASS_JAVA_LANG_THREADGROUP); @@ -1734,15 +692,17 @@ } /*! - * @todo Get @c @b ThreadGroup logic working that - * figures out which @c @b java.lang.ThreadGroup - * this thread is a part of and invoke - * @c @b java.lang.ThreadGroup.uncaughtException() - * for that specific object instead of this general method. - * Probably the class library will gripe about not knowing - * which object to associate with the method call since - * @c @b java.lang.ThreadGroup.uncaughtException() - * is @e not a @c @b static method. + * @todo HARMONY-6-jvm-opcode.c-9 Get @c @b ThreadGroup + * logic working that figures out which + * @c @b java.lang.ThreadGroup this thread is + * a part of and invoke + * @c @b java.lang.ThreadGroup.uncaughtException() + * for that specific object instead of this general + * method. Probably the class library will gripe + * about not knowing which object to associate with + * the method call since + * @c @b java.lang.ThreadGroup.uncaughtException() + * is @e not a @c @b static method. */ /* @@ -1820,7 +780,7 @@ if (rfalse == opcode_run(thridx, rfalse)) { /* Problem running error class, so quit */ - sysErrMsg("opcode_run", + sysErrMsg(arch_function_name, "Cannot run exception method %s %s%s", JVMCLASS_JAVA_LANG_THREADGROUP, JVMCFG_UNCAUGHT_EXCEPTION_METHOD, @@ -1844,7 +804,7 @@ /* Attempt to shut down thread due to condition */ if (rfalse == threadstate_request_complete(thridx)) { - sysErrMsg("opcode_run", + sysErrMsg(arch_function_name, "Unable to move completed thread %d to '%s' state", thridx, thread_state_get_name(THREAD_STATE_COMPLETE)); @@ -1858,7 +818,10 @@ } /* if THREAD_STATUS_THREW_UNCAUGHT */ else { - /*! @todo What needs to go here, if anything? */ + /*! + * @todo HARMONY-6-jvm-opcode.c-10 What needs to go here, + * if anything? + */ } /* Completely handled THREAD_STATUS_THREW_UNCAUGHT above */ @@ -1891,7 +854,7 @@ /* Attempt to shut down thread due to code completion */ if (rfalse == threadstate_request_complete(thridx)) { - sysErrMsg("opcode_run", + sysErrMsg(arch_function_name, "Unable to move aborted thread %d to '%s' state", thridx, thread_state_get_name( @@ -1904,7 +867,7 @@ } /* if nonlocal_rc */ - } /* if thread_exception_setup() */ + } /* if nonlocal_rc */ /***************************************************************/ /***************************************************************/ /***************************************************************/ @@ -1935,15 +898,26 @@ iswide = rfalse; jvm_virtual_opcode opcode; - u1 op1u1idx; /* Operand 1 as a (u1) CP index */ - u2 op1u2idx; /* Operand 1 as a (u2) CP index */ - u4 op1u4off; /* Operand 1 as a (u4) offset */ - + u1 op1u1; /* Operand 1 as a (u1) */ + u2 op1u2; /* Operand 1 as a (u2) */ + u4 op1u4; /* Operand 1 as a (u4) */ + rboolean rbool1; /* Conditional instruction status */ + + jbyte jbtmp; /* Opcode (jbyte) scratch area */ + jchar jctmp; /* Opcode (jchar) scratch area */ + jshort jstmp; /* Opcode (jshort) scratch area */ jint jitmp1; /* Opcode (jint) scratch area 1 */ jint jitmp2; /* Opcode (jint) scratch area 2 */ - jlong jltmp; /* Opcode (jlong) scratch area */ - jfloat jftmp; /* Opcode (jfloat) scratch area */ - jdouble jdtmp; /* Opcode (jdouble) scratch area */ + jint jitmp3; /* Opcode (jint) scratch area 3 */ + jint jitmp4; /* Opcode (jint) scratch area 4 */ + jlong jltmp1; /* Opcode (jlong) scratch area 1 */ + jlong jltmp2; /* Opcode (jlong) scratch area 2 */ + jfloat jftmp1; /* Opcode (jfloat) scratch area 1 */ + jfloat jftmp2; /* Opcode (jfloat) scratch area 2 */ + jdouble jdtmp1; /* Opcode (jdouble) scratch area 1*/ + jdouble jdtmp2; /* Opcode (jdouble) scratch area 2*/ + jvm_object_hash jotmp1; /* Opcode (jobject) scratch area 1*/ + jvm_object_hash jotmp2; /* Opcode (jobject) scratch area 2*/ /* Scratch area for Fieldref and Methodref navigation */ @@ -1968,7 +942,9 @@ /* Calls @c @b setjmp(3) to arm handler */ - nonlocal_thread_return = opcode_end_thread_setup(); + + nonlocal_thread_return = OPCODE_END_THREAD_SETUP( + &opcode_end_thread_nonlocal_return); /* Show error case first due to @e long switch() following */ if (EXIT_MAIN_OKAY != nonlocal_thread_return) @@ -1980,7 +956,7 @@ /*! * @internal For best runtime efficiency, place tests in - * order of most to least frequent occurrence. + * order of most to least frequent occurrence. */ while ( /* This thread is in the RUNNING state */ @@ -1990,6 +966,15 @@ ((rfalse == check_timeslice) || /* or if true and */ (rfalse == pjvm->timeslice_expired))) { + sysDbgMsg(DMLNORM, + arch_function_name, + "PC=%04.4x %04.4x %04.4x %04.4x opcode=%02.2x", + pc->clsidx, + pc->mthidx, + pc->codeatridx, + pc->excpatridx, + pcode[pc->offset]); + /* Retrieve next virtual opcode */ opcode = pcode[pc->offset++]; @@ -2003,16 +988,12 @@ static void dummy1(void) { char *p, *dummy2; dummy2 = p; dummy1(); } #define STUB { dummy1(); } -sysDbgMsg(0, "opcode.c", "opcode = %x", opcode); - switch(opcode) { case OPCODE_00_NOP: /* Do nothing */ break; case OPCODE_01_ACONST_NULL: /* Push NULL onto stack */ - /*! @todo Test this opcode */ - STUB; PUSH(thridx, FORCE_JINT(jvm_object_hash_null)); break; @@ -2028,11 +1009,9 @@ case OPCODE_09_LCONST_0: case OPCODE_0A_LCONST_1: - /*! @todo Test this opcode */ - STUB; - jltmp = (((jlong) opcode) - ((jlong) OPCODE_09_LCONST_0)); + jltmp1 = (((jlong) opcode) - ((jlong) OPCODE_09_LCONST_0)); - bytegames_split_jlong(jltmp, &jitmp1, &jitmp2); + bytegames_split_jlong(jltmp1, &jitmp1, &jitmp2); PUSH(thridx, jitmp1); /* ms word */ PUSH(thridx, jitmp2); /* ls word */ @@ -2041,20 +1020,16 @@ case OPCODE_0B_FCONST_0: case OPCODE_0C_FCONST_1: case OPCODE_0D_FCONST_2: - /*! @todo Test this opcode */ - STUB; - jftmp = (jfloat) (((jint) opcode) - ((jint) OPCODE_0B_FCONST_0)); + jftmp1 = (jfloat) (((jint) opcode) - ((jint) OPCODE_0B_FCONST_0)); - PUSH(thridx, FORCE_JINT(jftmp)); + PUSH(thridx, FORCE_JINT(jftmp1)); break; case OPCODE_0E_DCONST_0: case OPCODE_0F_DCONST_1: - /*! @todo Test this opcode */ - STUB; - jdtmp = (jdouble) (((jint) opcode) - ((jint) OPCODE_0E_DCONST_0)); + jdtmp1 = (jdouble) (((jint) opcode) - ((jint) OPCODE_0E_DCONST_0)); - bytegames_split_jdouble(jltmp, &jitmp1, &jitmp2); + bytegames_split_jdouble(jdtmp1, &jitmp1, &jitmp2); PUSH(thridx, jitmp1); /* ms word */ PUSH(thridx, jitmp2); /* ls word */ @@ -2062,670 +1037,1196 @@ break; case OPCODE_10_BIPUSH: - /*! @todo Write this opcode */ - STUB; + GET_U1_OPERAND(op1u1); + jbtmp = (jbyte) op1u1; /* Play sign extension games */ + jitmp1 = (jint) jbtmp; + + PUSH(thridx, jitmp1); break; case OPCODE_11_SIPUSH: - /*! @todo Write this opcode */ - STUB; + GET_U2_OPERAND(op1u2); + jstmp = (jshort) op1u2; /* Play sign extension games */ + jitmp1 = (jint) jstmp; + + PUSH(thridx, jitmp1); break; case OPCODE_12_LDC: - /*! @todo Write this opcode */ + /*! @todo HARMONY-6-jvm-opcode.c-11 Write this opcode */ STUB; break; case OPCODE_13_LDC_W: - /*! @todo Write this opcode */ + /*! @todo HARMONY-6-jvm-opcode.c-12 Write this opcode */ STUB; break; case OPCODE_14_LDC2_W: - /*! @todo Write this opcode */ + /*! @todo HARMONY-6-jvm-opcode.c-13 Write this opcode */ STUB; break; case OPCODE_15_ILOAD: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; + case_opcode_17_fload: + case_opcode_19_aload: + + GET_WIDE_OR_NORMAL_INDEX(jitmp1, 0); + + jitmp2 = GET_LOCAL_VAR(thridx, jitmp1); + PUSH(thridx, jitmp2); break; case OPCODE_16_LLOAD: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; + case_opcode_18_dload: + + GET_WIDE_OR_NORMAL_INDEX(jitmp1, 1); + + jitmp2 = GET_LOCAL_VAR(thridx, jitmp1); + jitmp3 = GET_LOCAL_VAR(thridx, jitmp1 + 1); + PUSH(thridx, jitmp2); + PUSH(thridx, jitmp3); break; case OPCODE_17_FLOAD: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; - break; + /*! + * @internal Instead of treating (jfloat) as a (jint), both + * being 1 word, one could treat it separately, even + * though there is more code required to do it. This + * is more formally "correct" at the expense of code + * complexity, although probably not run time. + * + * GET_WIDE_OR_NORMAL_INDEX(jitmp1, 0); + * + * jftmp1 = GET_LOCAL_VAR(thridx, jitmp1); + * + * PUSH(thridx, FORCE_JINT(jftmp1)); + * + * However, since all other types are simply moving + * (jint) words around, just follow suit in this case. + */ + + goto case_opcode_17_fload; /* Don't like 'goto', but makes sense */ case OPCODE_18_DLOAD: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; - break; + goto case_opcode_18_dload; /* Don't like 'goto', but makes sense */ case OPCODE_19_ALOAD: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; - break; + goto case_opcode_19_aload; /* Don't like 'goto', but makes sense */ case OPCODE_1A_ILOAD_0: case OPCODE_1B_ILOAD_1: case OPCODE_1C_ILOAD_2: case OPCODE_1D_ILOAD_3: - /*! @todo Write this opcode */ - STUB; + + jitmp1 = (((jint) opcode) - ((jint) OPCODE_1A_ILOAD_0)); + + jitmp2 = GET_LOCAL_VAR(thridx, jitmp1); + PUSH(thridx, jitmp2); break; case OPCODE_1E_LLOAD_0: case OPCODE_1F_LLOAD_1: case OPCODE_20_LLOAD_2: case OPCODE_21_LLOAD_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_1E_LLOAD_0)); + + jitmp2 = GET_LOCAL_VAR(thridx, jitmp1); + jitmp3 = GET_LOCAL_VAR(thridx, jitmp1 + 1); + PUSH(thridx, jitmp2); + PUSH(thridx, jitmp3); break; case OPCODE_22_FLOAD_0: case OPCODE_23_FLOAD_1: case OPCODE_24_FLOAD_2: case OPCODE_25_FLOAD_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_22_FLOAD_0)); + + jitmp2 = GET_LOCAL_VAR(thridx, jitmp1); + PUSH(thridx, jitmp2); break; case OPCODE_26_DLOAD_0: case OPCODE_27_DLOAD_1: case OPCODE_28_DLOAD_2: case OPCODE_29_DLOAD_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_26_DLOAD_0)); + + jitmp2 = GET_LOCAL_VAR(thridx, jitmp1); + jitmp3 = GET_LOCAL_VAR(thridx, jitmp1 + 1); + PUSH(thridx, jitmp2); + PUSH(thridx, jitmp3); break; case OPCODE_2A_ALOAD_0: case OPCODE_2B_ALOAD_1: case OPCODE_2C_ALOAD_2: case OPCODE_2D_ALOAD_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_2A_ALOAD_0)); + + jitmp2 = GET_LOCAL_VAR(thridx, jitmp1); + PUSH(thridx, jitmp2); break; case OPCODE_2E_IALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-84 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_I, jitmp1); + + jitmp2 = ((jint *) OBJECT(jotmp1).arraydata)[jitmp1]; + PUSH(thridx, jitmp2); break; case OPCODE_2F_LALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-85 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_J, jitmp1); + + jltmp1 = ((jlong *) OBJECT(jotmp1).arraydata)[jitmp1]; + + bytegames_split_jlong(jltmp1, &jitmp1, &jitmp2); + PUSH(thridx, jitmp1); + PUSH(thridx, jitmp2); break; case OPCODE_30_FALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-86 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_F, jitmp1); + + jftmp1 = ((jfloat *) OBJECT(jotmp1).arraydata)[jitmp1]; + PUSH(thridx, FORCE_JINT(jftmp1)); break; case OPCODE_31_DALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-87 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_D, jitmp1); + + jdtmp1 = ((jdouble *) OBJECT(jotmp1).arraydata)[jitmp1]; + + bytegames_split_jdouble(jdtmp1, &jitmp1, &jitmp2); + PUSH(thridx, jitmp1); + PUSH(thridx, jitmp2); break; case OPCODE_32_AALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-88 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_L, jitmp1); + + /*! @internal Careful! Use of 'jotmp1' as both rvalue and lvalue!*/ + jotmp1 = ((jvm_object_hash *) OBJECT(jotmp1).arraydata)[jitmp1]; + jitmp1 = (jint) jotmp1; + PUSH(thridx, jitmp1); break; case OPCODE_33_BALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-89 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_B, jitmp1); + + jbtmp = ((jbyte *) OBJECT(jotmp1).arraydata)[jitmp1]; + jitmp2 = (jint) jbtmp; /* Play sign extension games */ + PUSH(thridx, jitmp2); break; case OPCODE_34_CALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-90 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_C, jitmp1); + + jctmp = ((jchar *) OBJECT(jotmp1).arraydata)[jitmp1]; + jitmp2 = (jint) jctmp; /* Play sign extension games */ + PUSH(thridx, jitmp2); break; case OPCODE_35_SALOAD: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-91 Needs unit testing with real data*/ + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_S, jitmp1); + + jstmp = ((jshort *) OBJECT(jotmp1).arraydata)[jitmp1]; + jitmp2 = (jint) jstmp; /* Play sign extension games */ + PUSH(thridx, jitmp2); break; case OPCODE_36_ISTORE: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; + case_opcode_38_fstore: + case_opcode_3a_astore: + + GET_WIDE_OR_NORMAL_INDEX(jitmp1, 0); + + POP(thridx, jitmp2, jint); + PUT_LOCAL_VAR(thridx, jitmp1, jitmp2); break; case OPCODE_37_LSTORE: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; + case_opcode_39_lstore: + + GET_WIDE_OR_NORMAL_INDEX(jitmp1, 1); + + POP(thridx, jitmp3, jint); + POP(thridx, jitmp2, jint); + PUT_LOCAL_VAR(thridx, jitmp1, jitmp2); + PUT_LOCAL_VAR(thridx, jitmp1 + 1, jitmp3); break; case OPCODE_38_FSTORE: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; - break; + goto case_opcode_38_fstore; /* Don't like 'goto', but makes sense */ case OPCODE_39_DSTORE: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; - break; + goto case_opcode_39_lstore; /* Don't like 'goto', but makes sense */ case OPCODE_3A_ASTORE: - /*! @todo Write this opcode */ - STUB; - iswide = rfalse; - break; + goto case_opcode_3a_astore; /* Don't like 'goto', but makes sense */ case OPCODE_3B_ISTORE_0: case OPCODE_3C_ISTORE_1: case OPCODE_3D_ISTORE_2: case OPCODE_3E_ISTORE_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_3B_ISTORE_0)); + + POP(thridx, jitmp2, jint); + PUT_LOCAL_VAR(thridx, jitmp1, jitmp2); break; case OPCODE_3F_LSTORE_0: case OPCODE_40_LSTORE_1: case OPCODE_41_LSTORE_2: case OPCODE_42_LSTORE_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_3F_LSTORE_0)); + + POP(thridx, jitmp3, jint); + POP(thridx, jitmp2, jint); + PUT_LOCAL_VAR(thridx, jitmp1 + 1, jitmp3); + PUT_LOCAL_VAR(thridx, jitmp1, jitmp2); break; case OPCODE_43_FSTORE_0: case OPCODE_44_FSTORE_1: case OPCODE_45_FSTORE_2: case OPCODE_46_FSTORE_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_43_FSTORE_0)); + + POP(thridx, jitmp2, jint); + PUT_LOCAL_VAR(thridx, jitmp1, jitmp2); break; case OPCODE_47_DSTORE_0: case OPCODE_48_DSTORE_1: case OPCODE_49_DSTORE_2: case OPCODE_4A_DSTORE_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_47_DSTORE_0)); + + POP(thridx, jitmp3, jint); + POP(thridx, jitmp2, jint); + PUT_LOCAL_VAR(thridx, jitmp1 + 1, jitmp3); + PUT_LOCAL_VAR(thridx, jitmp1, jitmp2); break; case OPCODE_4B_ASTORE_0: case OPCODE_4C_ASTORE_1: case OPCODE_4D_ASTORE_2: case OPCODE_4E_ASTORE_3: - /*! @todo Write this opcode */ - STUB; + jitmp1 = (((jint) opcode) - ((jint) OPCODE_4B_ASTORE_0)); + + POP(thridx, jitmp2, jint); + PUT_LOCAL_VAR(thridx, jitmp1, jitmp2); break; case OPCODE_4F_IASTORE: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-92 Needs unit testing with real data*/ + + POP(thridx, jitmp2, jint); + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_I, jitmp1); + + ((jint *) OBJECT(jotmp1).arraydata)[jitmp1] = jitmp2; break; case OPCODE_50_LASTORE: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-93 Needs unit testing with real data*/ + + POP(thridx, jitmp3, jint); + POP(thridx, jitmp2, jint); + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_J, jitmp1); + + jltmp1 = bytegames_combine_jlong(jitmp2, jitmp3); + ((jlong *) OBJECT(jotmp1).arraydata)[jitmp1] = jltmp1; break; case OPCODE_51_FASTORE: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-94 Needs unit testing with real data*/ + + POP(thridx, jitmp2, jint); + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_F, jitmp1); + + jftmp1 = FORCE_JFLOAT(jitmp2); + ((jfloat *) OBJECT(jotmp1).arraydata)[jitmp1] = jftmp1; break; case OPCODE_52_DASTORE: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-95 Needs unit testing with real data*/ + + POP(thridx, jitmp3, jint); + POP(thridx, jitmp2, jint); + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_D, jitmp1); + + jdtmp1 = bytegames_combine_jdouble(jitmp2, jitmp3); + ((jdouble *) OBJECT(jotmp1).arraydata)[jitmp1] = jdtmp1; break; case OPCODE_53_AASTORE: - /*! @todo Write this opcode */ - STUB; + /*! @todo HARMONY-6-jvm-opcode.c-96 Needs unit testing with real data*/ + + POP(thridx, jitmp2, jint); + POP(thridx, jitmp1, jint); + POP(thridx, jotmp1, jvm_object_hash); + + VERIFY_OBJECT_HASH(jotmp1); + VERIFY_ARRAY_REFERENCE(jotmp1, BASETYPE_CHAR_L, jitmp1); + + ((jvm_object_hash *) OBJECT(jotmp1).arraydata)[jitmp1] = jitmp2; break; case OPCODE_54_BASTORE: - /*! @todo Write this opcode */ - STUB; [... 1569 lines stripped ...]