blob: 23732fac2dca3806235b819027eb72acb2ce0167 [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.
*/
#ifndef __CONTEXT6_H__
#define __CONTEXT6_H__
#include <assert.h>
#include <string.h>
#include "../base/context_x.h"
#include "stackmap_6.h"
//
// Context - main class of Type Checker
//
class vf_Context_6 : public vf_Context_x<vf_Context_6, WorkmapElement_6, _WorkmapElement_6, StackmapElement_6>
{
public:
vf_Context_6(SharedClasswideData &classwide) :
vf_Context_x<vf_Context_6, WorkmapElement_6, _WorkmapElement_6, StackmapElement_6>(classwide)
{}
vf_Result verify_method(Method_Handle method);
protected:
// stackmaps for instructions
InstrPropsBase props;
//init method-wide data
void init(Method_Handle _m_method) {
vf_Context_x<vf_Context_6, WorkmapElement_6, _WorkmapElement_6, StackmapElement_6>::init(_m_method);
props.init(mem, m_code_length);
}
// load derived types previously stored for the given instruction
void fill_workmap(Address instr) {
PropsHead_6 *head = (PropsHead_6*)props.getInstrProps(instr);
assert(sizeof(StackmapElement_6) == sizeof(WorkmapElement_6));
tc_memcpy(workmap, head->getStackmap(), sizeof(WorkmapHead) + sizeof(WorkmapElement_6) * (m_stack_start + head->stackmap.depth));
}
//create a stackmap vector of the given size sz (max_locals <= sz <= max_locals+max_stack)
PropsHead_6* newStackmap(int sz) {
return (PropsHead_6*)mem.calloc(sizeof(PropsHead_6) + sizeof(StackmapElement_6) * sz);
}
//parse StackMapTable attribute and store Stackmap vectors for the instructions
vf_Result load_stackmaptable();
//Read cnt types from a row bytearray representing StackMapTable and record to workmap starting at
//the specified element. If Long or Double happens in StackMapTable, record SM_HIGH_WORD after SM_LONG or SM_DOUBLE
//to the workmap and increase cnt. Check space_available when record to the workmap
vf_Result read_types(U_8** attr, U_8* end, WorkmapElement_6* element, unsigned* cnt, unsigned space_available);
/////////////////////////////////// "VIRTUAL" METHODS /////////////////////////////////////////////
public:
//create constraint vector in case of a branch
//simple conatraints are created for pairs of both locals and stack (current must be assignable to target)
vf_Result new_generic_vector_constraint(Address target_instr) {
StackmapHead *target = getStackmap(target_instr);
return target ? new_generic_vector_constraint_impl(target) : error(VF_ErrorBranch, "no stackmap at branch target");
}
//when we hit RET instruction we update the data for the given subroutine with current derived types
vf_Result new_ret_vector_constraint(Address target_instr) {
assert(0);
return error(VF_ErrorInternal, "unexpected JSR/RET instruction");
}
// Java5 anachronism: push catch-block to the stack of branches to pass, empty in Java6
void push_handler(Address handler_pc) {
}
//check stackmap for exception handler start
vf_Result checkHandlerStackmap(Address handler_pc, SmConstant type) {
StackmapHead *map = getStackmap(handler_pc);
if( !map ) {
return error(VF_ErrorHandler, "no stackmap at catch");
}
if( map->depth != 1 ) {
return error(VF_ErrorHandler, "incorrect stack at catch");
}
return add_incoming_value(type, &map->elements[m_stack_start]);
}
//returns stackmap for the 'instr' instruction or 0 if it does not exist
StackmapHead *getStackmap(Address instr) {
PropsHead_6 *pro = (PropsHead_6*) props.getInstrProps(instr);
return pro ? pro->getStackmap() : 0;
}
/////////////// expect some type //////////////
//expect exactly this type
int workmap_expect_strict( WorkmapElement_6 &el, SmConstant type ) {
assert(type != SM_BOGUS);
return type == el.const_val;
}
int workmap_expect( WorkmapElement_6 &el, SmConstant type ) {
return tpool.mustbe_assignable(el.const_val, type);
}
//create simple single constraint: "'from' is assingable to 'to'"
vf_Result new_scalar_constraint(WorkmapElement_6 *from, StackmapElement_6 *to) {
return add_incoming_value(from->const_val, to);
}
//add one more possible value (type) that can come to the given point (local or stack)
vf_Result add_incoming_value(SmConstant new_value, StackmapElement_6 *destination) {
return tpool.mustbe_assignable(new_value, destination->const_val) ? VF_OK :
error(VF_ErrorIncompatibleArgument, "incompatible argument");
}
//create special type of conatraint: "'from' is an array and it's element is assignable to 'to'"
vf_Result new_scalar_array2ref_constraint(WorkmapElement_6 *from, WorkmapElement_6 *to) {
//although new_scalar_conatraint() whould process from constants correctly
// we just do not need new variable if it is really a constant
*to = _WorkmapElement_6( tpool.get_ref_from_array(from->const_val) );
return VF_OK;
}
void new_bogus_propagation_constraint(WorkmapElement_6 &wm_el, SmConstant init_val) {
wm_el = _WorkmapElement_6 (init_val);
}
};
#endif