bool ph_var_equal(ph_variant_t *a, ph_variant_t *b) { if (a == b) { return true; } if (a->type != b->type) { return false; } switch (a->type) { case PH_VAR_INTEGER: return a->u.ival == b->u.ival; case PH_VAR_REAL: return a->u.dval == b->u.dval; case PH_VAR_STRING: return ph_string_equal(a->u.sval, b->u.sval); case PH_VAR_OBJECT: return obj_equal(a, b); case PH_VAR_ARRAY: return arr_equal(a, b); default: return false; } }
Expr* PrimInliner::tryInline() { // Returns the failure result or the result of the primitive (if the // primitive can't fail) if the primitive has been inlined; returns // NULL otherwise. If the primitive has been inlined but can't fail, // the bci in the MethodDecoder is set to the first instruction after // the failure block. // NB: The comparisons below should be replaced with pointer comparisons // comparing with the appropriate vmSymbol. Should fix this at some point. char* name = _pdesc->name(); Expr* res = NULL; switch (_pdesc->group()) { case IntArithmeticPrimitive: if (number_of_parameters() == 2) { Expr* x = parameter(0); Expr* y = parameter(1); if (equal(name, "primitiveAdd:ifFail:")) { res = smi_ArithmeticOp(tAddArithOp, x, y); break; } if (equal(name, "primitiveSubtract:ifFail:")) { res = smi_ArithmeticOp(tSubArithOp, x, y); break; } if (equal(name, "primitiveMultiply:ifFail:")) { res = smi_ArithmeticOp(tMulArithOp, x, y); break; } if (equal(name, "primitiveDiv:ifFail:")) { res = smi_Div(x, y); break; } if (equal(name, "primitiveMod:ifFail:")) { res = smi_Mod(x, y); break; } if (equal(name, "primitiveBitAnd:ifFail:")) { res = smi_BitOp(tAndArithOp, x, y); break; } if (equal(name, "primitiveBitOr:ifFail:")) { res = smi_BitOp(tOrArithOp , x, y); break; } if (equal(name, "primitiveBitXor:ifFail:")) { res = smi_BitOp(tXOrArithOp, x, y); break; } if (equal(name, "primitiveRawBitShift:ifFail:")) { res = smi_Shift(x, y); break; } } break; case IntComparisonPrimitive: if (number_of_parameters() == 2) { Expr* x = parameter(0); Expr* y = parameter(1); if (equal(name, "primitiveSmallIntegerEqual:ifFail:")) { res = smi_Comparison(EQBranchOp, x, y); break; } if (equal(name, "primitiveSmallIntegerNotEqual:ifFail:")) { res = smi_Comparison(NEBranchOp, x, y); break; } if (equal(name, "primitiveLessThan:ifFail:")) { res = smi_Comparison(LTBranchOp, x, y); break; } if (equal(name, "primitiveLessThanOrEqual:ifFail:")) { res = smi_Comparison(LEBranchOp, x, y); break; } if (equal(name, "primitiveGreaterThan:ifFail:")) { res = smi_Comparison(GTBranchOp, x, y); break; } if (equal(name, "primitiveGreaterThanOrEqual:ifFail:")) { res = smi_Comparison(GEBranchOp, x, y); break; } } break; case FloatArithmeticPrimitive: break; case FloatComparisonPrimitive: break; case ObjArrayPrimitive: if (equal(name, "primitiveIndexedObjectSize")) { res = array_size(); break; } if (equal(name, "primitiveIndexedObjectAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::object_at); break; } if (equal(name, "primitiveIndexedObjectAt:put:ifFail:")) { res = array_at_put_ifFail(ArrayAtPutNode::object_at_put); break; } break; case ByteArrayPrimitive: if (equal(name, "primitiveIndexedByteSize")) { res = array_size(); break; } if (equal(name, "primitiveIndexedByteAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::byte_at); break; } if (equal(name, "primitiveIndexedByteAt:put:ifFail:")) { res = array_at_put_ifFail(ArrayAtPutNode::byte_at_put); break; } break; case DoubleByteArrayPrimitive: if (equal(name, "primitiveIndexedDoubleByteSize")) { res = array_size(); break; } if (equal(name, "primitiveIndexedDoubleByteAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::double_byte_at); break; } if (equal(name, "primitiveIndexedDoubleByteCharacterAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::character_at); break; } if (equal(name, "primitiveIndexedDoubleByteAt:put:ifFail:")) { res = array_at_put_ifFail(ArrayAtPutNode::double_byte_at_put);break; } break; case BlockPrimitive: if (strncmp(name, "primitiveValue", 14) == 0) { res = block_primitiveValue(); break; } break; case NormalPrimitive: if (strncmp(name, "primitiveNew", 12) == 0) { res = obj_new(); break; } if (equal(name, "primitiveShallowCopyIfFail:ifFail:")) { res = obj_shallowCopy(); break; } if (equal(name, "primitiveEqual:")) { res = obj_equal(); break; } if (equal(name, "primitiveClass")) { res = obj_class(true); break; } if (equal(name, "primitiveClassOf:")) { res = obj_class(false); break; } if (equal(name, "primitiveHash")) { res = obj_hash(true); break; } if (equal(name, "primitiveHashOf:")) { res = obj_hash(false); break; } if (equal(name, "primitiveProxyByteAt:ifFail:")) { res = proxy_byte_at(); break; } if (equal(name, "primitiveProxyByteAt:put:ifFail:")) { res = proxy_byte_at_put(); break; } break; default: fatal1("bad primitive group %d", _pdesc->group()); break; } if (CompilerDebug) { cout(PrintInlining && (res != NULL))->print("%*sinlining %s %s\n", _scope->depth + 2, "", _pdesc->name(), _usingUncommonTrap ? "(unc. failure)" : (_cannotFail ? "(cannot fail)" : "")); } if (!_usingUncommonTrap && !_cannotFail) theCompiler->reporter->report_prim_failure(_pdesc); return res; }