Merge "ART: Fix typo in ArtMethod::FindCatchBlock"
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 1b70d59..8592aaa 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -82,6 +82,7 @@
optimizing/code_generator.cc \
optimizing/code_generator_arm.cc \
optimizing/code_generator_x86.cc \
+ optimizing/graph_visualizer.cc \
optimizing/nodes.cc \
optimizing/optimizing_compiler.cc \
optimizing/ssa_builder.cc \
diff --git a/compiler/compilers.h b/compiler/compilers.h
index 3ca78c9..e523d64 100644
--- a/compiler/compilers.h
+++ b/compiler/compilers.h
@@ -73,7 +73,7 @@
class OptimizingCompiler FINAL : public QuickCompiler {
public:
- explicit OptimizingCompiler(CompilerDriver* driver) : QuickCompiler(driver) { }
+ explicit OptimizingCompiler(CompilerDriver* driver);
CompiledMethod* Compile(const DexFile::CodeItem* code_item,
uint32_t access_flags,
@@ -92,6 +92,8 @@
const DexFile& dex_file) const;
private:
+ UniquePtr<std::ostream> visualizer_output_;
+
DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler);
};
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index d3477c9..435242a 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -268,6 +268,7 @@
MarkPossibleNullPointerException(opt_flags);
LoadConstantNoClobber(rs_r3, 0);
LIR* slow_unlock_branch = OpCmpBranch(kCondNe, rs_r1, rs_r2, NULL);
+ GenMemBarrier(kStoreLoad);
Store32Disp(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r3);
LIR* unlock_success_branch = OpUnconditionalBranch(NULL);
@@ -285,7 +286,6 @@
LIR* success_target = NewLIR0(kPseudoTargetLabel);
unlock_success_branch->target = success_target;
- GenMemBarrier(kStoreLoad);
} else {
// Explicit null-check as slow-path is entered using an IT.
GenNullCheck(rs_r0, opt_flags);
@@ -295,7 +295,8 @@
LoadConstantNoClobber(rs_r3, 0);
// Is lock unheld on lock or held by us (==thread_id) on unlock?
OpRegReg(kOpCmp, rs_r1, rs_r2);
- LIR* it = OpIT(kCondEq, "EE");
+ LIR* it = OpIT(kCondEq, "TEE");
+ GenMemBarrier(kStoreLoad);
Store32Disp/*eq*/(rs_r0, mirror::Object::MonitorOffset().Int32Value(), rs_r3);
// Go expensive route - UnlockObjectFromCode(obj);
LoadWordDisp/*ne*/(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(4, pUnlockObject).Int32Value(),
@@ -304,7 +305,6 @@
LIR* call_inst = OpReg(kOpBlx/*ne*/, rs_rARM_LR);
OpEndIT(it);
MarkSafepointPC(call_inst);
- GenMemBarrier(kStoreLoad);
}
}
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 7aaffcb..24ed4a3 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -801,8 +801,10 @@
const MethodReference& target_method,
uint32_t vtable_idx, uintptr_t direct_code,
uintptr_t direct_method, InvokeType type, bool skip_this) {
- int last_arg_reg = TargetReg(kArg3).GetReg();
- int next_reg = TargetReg(kArg1).GetReg();
+ int last_arg_reg = 3 - 1;
+ int arg_regs[3] = {TargetReg(kArg1).GetReg(), TargetReg(kArg2).GetReg(), TargetReg(kArg3).GetReg()};
+
+ int next_reg = 0;
int next_arg = 0;
if (skip_this) {
next_reg++;
@@ -811,8 +813,8 @@
for (; (next_reg <= last_arg_reg) && (next_arg < info->num_arg_words); next_reg++) {
RegLocation rl_arg = info->args[next_arg++];
rl_arg = UpdateRawLoc(rl_arg);
- if (rl_arg.wide && (next_reg <= TargetReg(kArg2).GetReg())) {
- RegStorage r_tmp(RegStorage::k64BitPair, next_reg, next_reg + 1);
+ if (rl_arg.wide && (next_reg <= last_arg_reg - 1)) {
+ RegStorage r_tmp(RegStorage::k64BitPair, arg_regs[next_reg], arg_regs[next_reg + 1]);
LoadValueDirectWideFixed(rl_arg, r_tmp);
next_reg++;
next_arg++;
@@ -821,7 +823,7 @@
rl_arg = NarrowRegLoc(rl_arg);
rl_arg.is_const = false;
}
- LoadValueDirectFixed(rl_arg, RegStorage::Solo32(next_reg));
+ LoadValueDirectFixed(rl_arg, RegStorage::Solo32(arg_regs[next_reg]));
}
call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
direct_code, direct_method, type);
@@ -1571,7 +1573,7 @@
RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
if (is_long) {
- if (cu_->instruction_set == kX86) {
+ if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
LoadBaseIndexedDisp(rl_object.reg, rl_offset.reg, 0, 0, rl_result.reg, k64);
} else {
RegStorage rl_temp_offset = AllocTemp();
@@ -1618,7 +1620,7 @@
RegLocation rl_value;
if (is_long) {
rl_value = LoadValueWide(rl_src_value, kCoreReg);
- if (cu_->instruction_set == kX86) {
+ if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
StoreBaseIndexedDisp(rl_object.reg, rl_offset.reg, 0, 0, rl_value.reg, k64);
} else {
RegStorage rl_temp_offset = AllocTemp();
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 77119a4..2c4ca88 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -37,7 +37,7 @@
}
// TODO: needs revisit for 64-bit.
-RegStorage Mir2Lir::LoadArg(int in_position, bool wide) {
+RegStorage Mir2Lir::LoadArg(int in_position, RegisterClass reg_class, bool wide) {
RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
RegStorage reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) :
RegStorage::InvalidReg();
@@ -56,28 +56,45 @@
if (wide && !reg_arg_high.Valid()) {
// If the low part is not in a reg, we allocate a pair. Otherwise, we just load to high reg.
if (!reg_arg_low.Valid()) {
- RegStorage new_regs = AllocTypedTempWide(false, kAnyReg);
- reg_arg_low = new_regs.GetLow();
- reg_arg_high = new_regs.GetHigh();
+ RegStorage new_regs = AllocTypedTempWide(false, reg_class);
LoadBaseDisp(TargetReg(kSp), offset, new_regs, k64);
+ return new_regs; // The reg_class is OK, we can return.
} else {
+ // Assume that no ABI allows splitting a wide fp reg between a narrow fp reg and memory,
+ // i.e. the low part is in a core reg. Load the second part in a core reg as well for now.
+ DCHECK(!reg_arg_low.IsFloat());
reg_arg_high = AllocTemp();
int offset_high = offset + sizeof(uint32_t);
Load32Disp(TargetReg(kSp), offset_high, reg_arg_high);
+ // Continue below to check the reg_class.
}
}
// If the low part is not in a register yet, we need to load it.
if (!reg_arg_low.Valid()) {
- reg_arg_low = AllocTemp();
+ // Assume that if the low part of a wide arg is passed in memory, so is the high part,
+ // thus we don't get here for wide args as it's handled above. Big-endian ABIs could
+ // conceivably break this assumption but Android supports only little-endian architectures.
+ DCHECK(!wide);
+ reg_arg_low = AllocTypedTemp(false, reg_class);
Load32Disp(TargetReg(kSp), offset, reg_arg_low);
+ return reg_arg_low; // The reg_class is OK, we can return.
}
- if (wide) {
- return RegStorage::MakeRegPair(reg_arg_low, reg_arg_high);
- } else {
- return reg_arg_low;
+ RegStorage reg_arg = wide ? RegStorage::MakeRegPair(reg_arg_low, reg_arg_high) : reg_arg_low;
+ // Check if we need to copy the arg to a different reg_class.
+ if (!RegClassMatches(reg_class, reg_arg)) {
+ if (wide) {
+ RegStorage new_regs = AllocTypedTempWide(false, reg_class);
+ OpRegCopyWide(new_regs, reg_arg);
+ reg_arg = new_regs;
+ } else {
+ RegStorage new_reg = AllocTypedTemp(false, reg_class);
+ OpRegCopy(new_reg, reg_arg);
+ reg_arg = new_reg;
+ }
}
+ return reg_arg;
}
void Mir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) {
@@ -138,16 +155,29 @@
// Point of no return - no aborts after this
GenPrintLabel(mir);
LockArg(data.object_arg);
+ RegStorage reg_obj = LoadArg(data.object_arg, kCoreReg);
RegLocation rl_dest = wide ? GetReturnWide(double_or_float) : GetReturn(double_or_float);
- RegStorage reg_obj = LoadArg(data.object_arg);
+ RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile);
+ RegStorage r_result = rl_dest.reg;
+ if (!RegClassMatches(reg_class, r_result)) {
+ r_result = wide ? AllocTypedTempWide(rl_dest.fp, reg_class)
+ : AllocTypedTemp(rl_dest.fp, reg_class);
+ }
if (data.is_volatile) {
- LoadBaseDispVolatile(reg_obj, data.field_offset, rl_dest.reg, size);
+ LoadBaseDispVolatile(reg_obj, data.field_offset, r_result, size);
// Without context sensitive analysis, we must issue the most conservative barriers.
// In this case, either a load or store may follow so we issue both barriers.
GenMemBarrier(kLoadLoad);
GenMemBarrier(kLoadStore);
} else {
- LoadBaseDisp(reg_obj, data.field_offset, rl_dest.reg, size);
+ LoadBaseDisp(reg_obj, data.field_offset, r_result, size);
+ }
+ if (r_result != rl_dest.reg) {
+ if (wide) {
+ OpRegCopyWide(rl_dest.reg, r_result);
+ } else {
+ OpRegCopy(rl_dest.reg, r_result);
+ }
}
return true;
}
@@ -175,8 +205,9 @@
GenPrintLabel(mir);
LockArg(data.object_arg);
LockArg(data.src_arg, wide);
- RegStorage reg_obj = LoadArg(data.object_arg);
- RegStorage reg_src = LoadArg(data.src_arg, wide);
+ RegStorage reg_obj = LoadArg(data.object_arg, kCoreReg);
+ RegisterClass reg_class = RegClassForFieldLoadStore(size, data.is_volatile);
+ RegStorage reg_src = LoadArg(data.src_arg, reg_class, wide);
if (data.is_volatile) {
// There might have been a store before this volatile one so insert StoreStore barrier.
GenMemBarrier(kStoreStore);
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 77e5649..6a0f3b2 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -1397,7 +1397,7 @@
* @param wide Whether the argument is 64-bit or not.
* @return Returns the register (or register pair) for the loaded argument.
*/
- RegStorage LoadArg(int in_position, bool wide = false);
+ RegStorage LoadArg(int in_position, RegisterClass reg_class, bool wide = false);
/**
* @brief Used to load a VR argument directly to a specified register location.
diff --git a/compiler/elf_writer_mclinker.cc b/compiler/elf_writer_mclinker.cc
index eb9b230..aa4a5b2 100644
--- a/compiler/elf_writer_mclinker.cc
+++ b/compiler/elf_writer_mclinker.cc
@@ -361,8 +361,9 @@
ClassLinker* linker = Runtime::Current()->GetClassLinker();
// Unchecked as we hold mutator_lock_ on entry.
ScopedObjectAccessUnchecked soa(Thread::Current());
- Handle<mirror::DexCache> dex_cache(soa.Self(), linker->FindDexCache(dex_file));
- Handle<mirror::ClassLoader> class_loader(soa.Self(), nullptr);
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(dex_file)));
+ auto class_loader(hs.NewHandle<mirror::ClassLoader>(nullptr));
method = linker->ResolveMethod(dex_file, method_idx, dex_cache, class_loader, NULL, invoke_type);
CHECK(method != NULL);
}
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index b0aa63b..2c2564d 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -311,6 +311,10 @@
}
}
+ if (return_type == Primitive::kPrimDouble || return_type == Primitive::kPrimFloat) {
+ return false;
+ }
+
DCHECK_EQ(argument_index, number_of_arguments);
current_block_->AddInstruction(invoke);
return true;
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index bbebd3a..beafbcc 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -47,7 +47,7 @@
Bind(GetLabelOf(block));
HGraphVisitor* location_builder = GetLocationBuilder();
HGraphVisitor* instruction_visitor = GetInstructionVisitor();
- for (HInstructionIterator it(*block->GetInstructions()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
current->Accept(location_builder);
InitLocations(current);
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
new file mode 100644
index 0000000..a7604be
--- /dev/null
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#include "graph_visualizer.h"
+
+#include "driver/dex_compilation_unit.h"
+#include "nodes.h"
+
+namespace art {
+
+/**
+ * HGraph visitor to generate a file suitable for the c1visualizer tool and IRHydra.
+ */
+class HGraphVisualizerPrinter : public HGraphVisitor {
+ public:
+ HGraphVisualizerPrinter(HGraph* graph, std::ostream& output)
+ : HGraphVisitor(graph), output_(output), indent_(0) {}
+
+ void StartTag(const char* name) {
+ AddIndent();
+ output_ << "begin_" << name << std::endl;
+ indent_++;
+ }
+
+ void EndTag(const char* name) {
+ indent_--;
+ AddIndent();
+ output_ << "end_" << name << std::endl;
+ }
+
+ void PrintProperty(const char* name, const char* property) {
+ AddIndent();
+ output_ << name << " \"" << property << "\"" << std::endl;
+ }
+
+ void PrintProperty(const char* name, const char* property, int id) {
+ AddIndent();
+ output_ << name << " \"" << property << id << "\"" << std::endl;
+ }
+
+ void PrintEmptyProperty(const char* name) {
+ AddIndent();
+ output_ << name << std::endl;
+ }
+
+ void PrintTime(const char* name) {
+ AddIndent();
+ output_ << name << " " << time(NULL) << std::endl;
+ }
+
+ void PrintInt(const char* name, int value) {
+ AddIndent();
+ output_ << name << " " << value << std::endl;
+ }
+
+ void AddIndent() {
+ for (size_t i = 0; i < indent_; ++i) {
+ output_ << " ";
+ }
+ }
+
+ void PrintPredecessors(HBasicBlock* block) {
+ AddIndent();
+ output_ << "predecessors";
+ for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
+ HBasicBlock* predecessor = block->GetPredecessors().Get(i);
+ output_ << " \"B" << predecessor->GetBlockId() << "\" ";
+ }
+ output_<< std::endl;
+ }
+
+ void PrintSuccessors(HBasicBlock* block) {
+ AddIndent();
+ output_ << "successors";
+ for (size_t i = 0, e = block->GetSuccessors().Size(); i < e; ++i) {
+ HBasicBlock* successor = block->GetSuccessors().Get(i);
+ output_ << " \"B" << successor->GetBlockId() << "\" ";
+ }
+ output_<< std::endl;
+ }
+
+
+ void VisitInstruction(HInstruction* instruction) {
+ output_ << instruction->DebugName();
+ if (instruction->InputCount() > 0) {
+ output_ << " [ ";
+ for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
+ output_ << "v" << inputs.Current()->GetId() << " ";
+ }
+ output_ << "]";
+ }
+ }
+
+ void PrintInstructions(const HInstructionList& list) {
+ const char* kEndInstructionMarker = "<|@";
+ for (HInstructionIterator it(list); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
+ AddIndent();
+ int bci = 0;
+ output_ << bci << " " << instruction->NumberOfUses() << " v" << instruction->GetId() << " ";
+ instruction->Accept(this);
+ output_ << kEndInstructionMarker << std::endl;
+ }
+ }
+
+ void Run(const char* pass_name) {
+ StartTag("cfg");
+ PrintProperty("name", pass_name);
+ VisitInsertionOrder();
+ EndTag("cfg");
+ }
+
+ void VisitBasicBlock(HBasicBlock* block) {
+ StartTag("block");
+ PrintProperty("name", "B", block->GetBlockId());
+ PrintInt("from_bci", -1);
+ PrintInt("to_bci", -1);
+ PrintPredecessors(block);
+ PrintSuccessors(block);
+ PrintEmptyProperty("xhandlers");
+ PrintEmptyProperty("flags");
+ if (block->GetDominator() != nullptr) {
+ PrintProperty("dominator", "B", block->GetDominator()->GetBlockId());
+ }
+
+ StartTag("states");
+ StartTag("locals");
+ PrintInt("size", 0);
+ PrintProperty("method", "None");
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+ AddIndent();
+ HInstruction* instruction = it.Current();
+ output_ << instruction->GetId() << " v" << instruction->GetId() << "[ ";
+ for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
+ output_ << inputs.Current()->GetId() << " ";
+ }
+ output_ << "]" << std::endl;
+ }
+ EndTag("locals");
+ EndTag("states");
+
+ StartTag("HIR");
+ PrintInstructions(block->GetPhis());
+ PrintInstructions(block->GetInstructions());
+ EndTag("HIR");
+ EndTag("block");
+ }
+
+ private:
+ std::ostream& output_;
+ size_t indent_;
+
+ DISALLOW_COPY_AND_ASSIGN(HGraphVisualizerPrinter);
+};
+
+HGraphVisualizer::HGraphVisualizer(std::ostream* output,
+ HGraph* graph,
+ const char* string_filter,
+ const DexCompilationUnit& cu)
+ : output_(output), graph_(graph), is_enabled_(false) {
+ if (output == nullptr) {
+ return;
+ }
+ std::string pretty_name = PrettyMethod(cu.GetDexMethodIndex(), *cu.GetDexFile());
+ if (pretty_name.find(string_filter) == std::string::npos) {
+ return;
+ }
+
+ is_enabled_ = true;
+ HGraphVisualizerPrinter printer(graph, *output_);
+ printer.StartTag("compilation");
+ printer.PrintProperty("name", pretty_name.c_str());
+ printer.PrintProperty("method", pretty_name.c_str());
+ printer.PrintTime("date");
+ printer.EndTag("compilation");
+}
+
+void HGraphVisualizer::DumpGraph(const char* pass_name) {
+ if (!is_enabled_) {
+ return;
+ }
+ HGraphVisualizerPrinter printer(graph_, *output_);
+ printer.Run(pass_name);
+}
+
+} // namespace art
diff --git a/compiler/optimizing/graph_visualizer.h b/compiler/optimizing/graph_visualizer.h
new file mode 100644
index 0000000..433d55d
--- /dev/null
+++ b/compiler/optimizing/graph_visualizer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
+#define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
+
+#include "utils/allocation.h"
+
+namespace art {
+
+class DexCompilationUnit;
+class HGraph;
+
+/**
+ * If enabled, emits compilation information suitable for the c1visualizer tool
+ * and IRHydra.
+ * Currently only works if the compiler is single threaded.
+ */
+class HGraphVisualizer : public ValueObject {
+ public:
+ /**
+ * If output is not null, and the method name of the dex compilation
+ * unit contains `string_filter`, the compilation information will be
+ * emitted.
+ */
+ HGraphVisualizer(std::ostream* output,
+ HGraph* graph,
+ const char* string_filter,
+ const DexCompilationUnit& cu);
+
+ /**
+ * If this visualizer is enabled, emit the compilation information
+ * in `output_`.
+ */
+ void DumpGraph(const char* pass_name);
+
+ private:
+ std::ostream* const output_;
+ HGraph* const graph_;
+
+ // Is true when `output_` is not null, and the compiled method's name
+ // contains the string_filter given in the constructor.
+ bool is_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index cf2d1ee..afaedd7 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -37,10 +37,10 @@
for (size_t j = 0; j < block->GetSuccessors().Size(); ++j) {
block->GetSuccessors().Get(j)->RemovePredecessor(block, false);
}
- for (HInstructionIterator it(*block->GetPhis()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
block->RemovePhi(it.Current()->AsPhi());
}
- for (HInstructionIterator it(*block->GetInstructions()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
block->RemoveInstruction(it.Current());
}
}
@@ -420,10 +420,10 @@
}
void HGraphVisitor::VisitBasicBlock(HBasicBlock* block) {
- for (HInstructionIterator it(*block->GetPhis()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
- for (HInstructionIterator it(*block->GetInstructions()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
}
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 081c2bd..27b87ca 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -82,7 +82,7 @@
void SimplifyCFG();
// Find all natural loops in this graph. Aborts computation and returns false
- // if one loop is not natural, that is the header does not dominated the back
+ // if one loop is not natural, that is the header does not dominate the back
// edge.
bool FindNaturalLoops() const;
@@ -268,8 +268,8 @@
HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
- HInstructionList const* GetInstructions() const { return &instructions_; }
- HInstructionList const* GetPhis() const { return &phis_; }
+ const HInstructionList& GetInstructions() const { return instructions_; }
+ const HInstructionList& GetPhis() const { return phis_; }
void AddSuccessor(HBasicBlock* block) {
successors_.Add(block);
@@ -444,6 +444,17 @@
bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
+ size_t NumberOfUses() const {
+ // TODO: Optimize this method if it is used outside of the HGraphTracer.
+ size_t result = 0;
+ HUseListNode<HInstruction>* current = uses_;
+ while (current != nullptr) {
+ current = current->GetTail();
+ ++result;
+ }
+ return result;
+ }
+
int GetId() const { return id_; }
void SetId(int id) { id_ = id; }
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index a5031e0..f435cb0 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <fstream>
#include <stdint.h>
#include "builder.h"
@@ -21,6 +22,7 @@
#include "compilers.h"
#include "driver/compiler_driver.h"
#include "driver/dex_compilation_unit.h"
+#include "graph_visualizer.h"
#include "nodes.h"
#include "ssa_liveness_analysis.h"
#include "utils/arena_allocator.h"
@@ -50,6 +52,22 @@
DISALLOW_COPY_AND_ASSIGN(CodeVectorAllocator);
};
+/**
+ * If set to true, generates a file suitable for the c1visualizer tool and IRHydra.
+ */
+static bool kIsVisualizerEnabled = false;
+
+/**
+ * Filter to apply to the visualizer. Methods whose name contain that filter will
+ * be in the file.
+ */
+static const char* kStringFilter = "";
+
+OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver) : QuickCompiler(driver) {
+ if (kIsVisualizerEnabled) {
+ visualizer_output_.reset(new std::ofstream("art.cfg"));
+ }
+}
CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_item,
uint32_t access_flags,
@@ -70,6 +88,7 @@
ArenaPool pool;
ArenaAllocator arena(&pool);
HGraphBuilder builder(&arena, &dex_compilation_unit, &dex_file);
+
HGraph* graph = builder.BuildGraph(*code_item);
if (graph == nullptr) {
if (shouldCompile) {
@@ -77,6 +96,8 @@
}
return nullptr;
}
+ HGraphVisualizer visualizer(visualizer_output_.get(), graph, kStringFilter, dex_compilation_unit);
+ visualizer.DumpGraph("builder");
InstructionSet instruction_set = GetCompilerDriver()->GetInstructionSet();
// The optimizing compiler currently does not have a Thumb2 assembler.
@@ -104,6 +125,8 @@
// Run these phases to get some test coverage.
graph->BuildDominatorTree();
graph->TransformToSSA();
+ visualizer.DumpGraph("ssa");
+
graph->FindNaturalLoops();
SsaLivenessAnalysis(*graph).Analyze();
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 1fc041c..50e3254 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -30,7 +30,7 @@
// 2) Set inputs of loop phis.
for (size_t i = 0; i < loop_headers_.Size(); i++) {
HBasicBlock* block = loop_headers_.Get(i);
- for (HInstructionIterator it(*block->GetPhis()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
HPhi* phi = it.Current()->AsPhi();
for (size_t pred = 0; pred < block->GetPredecessors().Size(); pred++) {
phi->AddInput(ValueOfLocal(block->GetPredecessors().Get(pred), phi->GetRegNumber()));
@@ -40,7 +40,7 @@
// 3) Clear locals.
// TODO: Move this to a dead code eliminator phase.
- for (HInstructionIterator it(*GetGraph()->GetEntryBlock()->GetInstructions());
+ for (HInstructionIterator it(GetGraph()->GetEntryBlock()->GetInstructions());
!it.Done();
it.Advance()) {
HInstruction* current = it.Current();
@@ -106,7 +106,7 @@
// - HStoreLocal: update current value of the local and remove the instruction.
// - Instructions that require an environment: populate their environment
// with the current values of the locals.
- for (HInstructionIterator it(*block->GetInstructions()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
}
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 0ab77ca..7c2ec39 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -29,14 +29,14 @@
for (HReversePostOrderIterator it(graph_); !it.Done(); it.Advance()) {
HBasicBlock* block = it.Current();
- for (HInstructionIterator it(*block->GetPhis()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasUses()) {
current->SetSsaIndex(ssa_index++);
}
}
- for (HInstructionIterator it(*block->GetInstructions()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasUses()) {
current->SetSsaIndex(ssa_index++);
@@ -73,7 +73,7 @@
BitVector* kill = GetKillSet(*block);
BitVector* live_in = GetLiveInSet(*block);
- for (HBackwardInstructionIterator it(*block->GetInstructions()); !it.Done(); it.Advance()) {
+ for (HBackwardInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasSsaIndex()) {
kill->SetBit(current->GetSsaIndex());
@@ -99,7 +99,7 @@
}
}
- for (HInstructionIterator it(*block->GetPhis()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->HasSsaIndex()) {
kill->SetBit(current->GetSsaIndex());
diff --git a/compiler/optimizing/ssa_test.cc b/compiler/optimizing/ssa_test.cc
index 9be2197..415d146 100644
--- a/compiler/optimizing/ssa_test.cc
+++ b/compiler/optimizing/ssa_test.cc
@@ -66,10 +66,10 @@
int id = 0;
for (size_t i = 0, e = graph->GetBlocks().Size(); i < e; ++i) {
HBasicBlock* block = graph->GetBlocks().Get(i);
- for (HInstructionIterator it(*block->GetPhis()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
it.Current()->SetId(id++);
}
- for (HInstructionIterator it(*block->GetInstructions()); !it.Done(); it.Advance()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
it.Current()->SetId(id++);
}
}
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 7d7024a..ad796f8 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -958,9 +958,7 @@
bool image = (!image_filename.empty());
if (!image && boot_image_filename.empty()) {
boot_image_filename += GetAndroidRoot();
- boot_image_filename += "/framework/boot-";
- boot_image_filename += GetInstructionSetString(instruction_set);
- boot_image_filename += ".art";
+ boot_image_filename += "/framework/boot.art";
}
std::string boot_image_option;
if (!boot_image_filename.empty()) {
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 4886561..5212576 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -399,7 +399,7 @@
@ unlocked case - r2 holds thread id with count of 0
strex r3, r2, [r0, #LOCK_WORD_OFFSET]
cbnz r3, .Lstrex_fail @ store failed, retry
- dmb ish @ full (LoadLoad) memory barrier
+ dmb ish @ full (LoadLoad|LoadStore) memory barrier
bx lr
.Lstrex_fail:
b .Lretry_lock @ unlikely forward branch, need to reload and recheck r1/r2
@@ -442,7 +442,7 @@
cmp r1, #65536
bpl .Lrecursive_thin_unlock
@ transition to unlocked, r3 holds 0
- dmb ish @ full (StoreLoad) memory barrier
+ dmb ish @ full (LoadStore|StoreStore) memory barrier
str r3, [r0, #LOCK_WORD_OFFSET]
bx lr
.Lrecursive_thin_unlock:
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 2a21144..f2050b3 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -1014,7 +1014,7 @@
cbnz w1, .Lnot_unlocked // already thin locked
stxr w3, w2, [x4]
cbnz w3, .Lstrex_fail // store failed, retry
- dmb ishld // full (LoadLoad) memory barrier, TODO: acquire-release
+ dmb ishld // full (LoadLoad|LoadStore) memory barrier
ret
.Lstrex_fail:
b .Lretry_lock // unlikely forward branch, need to reload and recheck r1/r2
@@ -1058,7 +1058,7 @@
cmp w1, #65536
bpl .Lrecursive_thin_unlock
// transition to unlocked, w3 holds 0
- dmb ish // full (StoreLoad) memory barrier
+ dmb ish // full (LoadStore|StoreStore) memory barrier
str w3, [x0, #LOCK_WORD_OFFSET]
ret
.Lrecursive_thin_unlock:
@@ -1444,7 +1444,7 @@
* | RDI/Method* | <- X0
* #-------------------#
* | local ref cookie | // 4B
- * | handle scope size | // 4B
+ * | handle scope size | // 4B
* #-------------------#
* | JNI Call Stack |
* #-------------------# <--- SP on native call
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 73214ea..9c86c75 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -1050,12 +1050,12 @@
* | Return |
* | Callee-Save Data |
* #-------------------#
- * | handle scope |
+ * | handle scope |
* #-------------------#
* | Method* | <--- (1)
* #-------------------#
* | local ref cookie | // 4B
- * | handle scope size | // 4B TODO: roll into call stack alignment?
+ * | handle scope size | // 4B TODO: roll into call stack alignment?
* #-------------------#
* | JNI Call Stack |
* #-------------------# <--- SP on native call
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 0d5a805..cfd0c00 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -179,7 +179,7 @@
// times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
// circumstances, but this is incorrect.
void CheckClassName(const char* class_name) {
- if (!IsValidJniClassName(class_name)) {
+ if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
JniAbortF(function_name_,
"illegal class name '%s'\n"
" (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 3d268e4..9034560 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2215,7 +2215,10 @@
DCHECK(self->IsExceptionPending());
return nullptr;
}
-
+ if (UNLIKELY(component_type->IsPrimitiveVoid())) {
+ ThrowNoClassDefFoundError("Attempt to create array of void primitive type");
+ return nullptr;
+ }
// See if the component type is already loaded. Array classes are
// always associated with the class loader of their underlying
// element type -- an array of Strings goes with the loader for
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index b9b51fd..634f2be 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -25,7 +25,7 @@
namespace art {
template<size_t kNumReferences>
-StackHandleScope<kNumReferences>::StackHandleScope(Thread* self)
+inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self)
: HandleScope(kNumReferences), self_(self), pos_(0) {
// TODO: Figure out how to use a compile assert.
DCHECK_EQ(OFFSETOF_MEMBER(HandleScope, references_),
@@ -37,7 +37,7 @@
}
template<size_t kNumReferences>
-StackHandleScope<kNumReferences>::~StackHandleScope() {
+inline StackHandleScope<kNumReferences>::~StackHandleScope() {
HandleScope* top_handle_scope = self_->PopHandleScope();
DCHECK_EQ(top_handle_scope, this);
}
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 4634971..21dab8d 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -518,16 +518,28 @@
SafeMap<std::string, SharedLibrary*> libraries_;
};
-#define CHECK_NON_NULL_ARGUMENT(value) CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value)
+#define CHECK_NON_NULL_ARGUMENT(value) \
+ CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, nullptr)
-#define CHECK_NON_NULL_ARGUMENT_FN_NAME(name, value) \
+#define CHECK_NON_NULL_ARGUMENT_RETURN_VOID(value) \
+ CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, )
+
+#define CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(value) \
+ CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, 0)
+
+#define CHECK_NON_NULL_ARGUMENT_RETURN(value, return_val) \
+ CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, return_val)
+
+#define CHECK_NON_NULL_ARGUMENT_FN_NAME(name, value, return_val) \
if (UNLIKELY(value == nullptr)) { \
JniAbortF(name, #value " == null"); \
+ return return_val; \
}
#define CHECK_NON_NULL_MEMCPY_ARGUMENT(length, value) \
if (UNLIKELY(length != 0 && value == nullptr)) { \
JniAbortF(__FUNCTION__, #value " == null"); \
+ return; \
}
class JNI {
@@ -614,8 +626,8 @@
}
static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
- CHECK_NON_NULL_ARGUMENT(java_class1);
- CHECK_NON_NULL_ARGUMENT(java_class2);
+ CHECK_NON_NULL_ARGUMENT_RETURN(java_class1, JNI_FALSE);
+ CHECK_NON_NULL_ARGUMENT_RETURN(java_class2, JNI_FALSE);
ScopedObjectAccess soa(env);
mirror::Class* c1 = soa.Decode<mirror::Class*>(java_class1);
mirror::Class* c2 = soa.Decode<mirror::Class*>(java_class2);
@@ -623,7 +635,7 @@
}
static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) {
- CHECK_NON_NULL_ARGUMENT(java_class);
+ CHECK_NON_NULL_ARGUMENT_RETURN(java_class, JNI_FALSE);
if (jobj == nullptr) {
// Note: JNI is different from regular Java instanceof in this respect
return JNI_TRUE;
@@ -647,7 +659,7 @@
}
static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) {
- CHECK_NON_NULL_ARGUMENT(c);
+ CHECK_NON_NULL_ARGUMENT_RETURN(c, JNI_ERR);
return ThrowNewException(env, c, msg, nullptr);
}
@@ -914,8 +926,8 @@
static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -923,15 +935,15 @@
}
static jboolean CallBooleanMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetZ();
}
static jboolean CallBooleanMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetZ();
@@ -940,8 +952,8 @@
static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -949,15 +961,15 @@
}
static jbyte CallByteMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetB();
}
static jbyte CallByteMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetB();
@@ -966,8 +978,8 @@
static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -975,15 +987,15 @@
}
static jchar CallCharMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetC();
}
static jchar CallCharMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetC();
@@ -992,8 +1004,8 @@
static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1001,15 +1013,15 @@
}
static jdouble CallDoubleMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetD();
}
static jdouble CallDoubleMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetD();
@@ -1018,8 +1030,8 @@
static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1027,15 +1039,15 @@
}
static jfloat CallFloatMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetF();
}
static jfloat CallFloatMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetF();
@@ -1044,8 +1056,8 @@
static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1053,15 +1065,15 @@
}
static jint CallIntMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetI();
}
static jint CallIntMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetI();
@@ -1070,8 +1082,8 @@
static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1079,15 +1091,15 @@
}
static jlong CallLongMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetJ();
}
static jlong CallLongMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetJ();
@@ -1096,8 +1108,8 @@
static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1105,15 +1117,15 @@
}
static jshort CallShortMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetS();
}
static jshort CallShortMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
args).GetS();
@@ -1122,23 +1134,23 @@
static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap);
va_end(ap);
}
static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args);
}
static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args);
}
@@ -1177,8 +1189,8 @@
...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1187,16 +1199,16 @@
static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetZ();
}
static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetZ();
}
@@ -1204,8 +1216,8 @@
static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1214,16 +1226,16 @@
static jbyte CallNonvirtualByteMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetB();
}
static jbyte CallNonvirtualByteMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetB();
}
@@ -1231,8 +1243,8 @@
static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1241,16 +1253,16 @@
static jchar CallNonvirtualCharMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetC();
}
static jchar CallNonvirtualCharMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetC();
}
@@ -1258,8 +1270,8 @@
static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1268,16 +1280,16 @@
static jshort CallNonvirtualShortMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetS();
}
static jshort CallNonvirtualShortMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetS();
}
@@ -1285,8 +1297,8 @@
static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1295,16 +1307,16 @@
static jint CallNonvirtualIntMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetI();
}
static jint CallNonvirtualIntMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetI();
}
@@ -1312,8 +1324,8 @@
static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1322,16 +1334,16 @@
static jlong CallNonvirtualLongMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetJ();
}
static jlong CallNonvirtualLongMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetJ();
}
@@ -1339,8 +1351,8 @@
static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1349,16 +1361,16 @@
static jfloat CallNonvirtualFloatMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetF();
}
static jfloat CallNonvirtualFloatMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetF();
}
@@ -1366,8 +1378,8 @@
static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
va_end(ap);
@@ -1376,16 +1388,16 @@
static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, obj, mid, args).GetD();
}
static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetD();
}
@@ -1393,8 +1405,8 @@
static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeWithVarArgs(soa, obj, mid, ap);
va_end(ap);
@@ -1402,16 +1414,16 @@
static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
va_list args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeWithVarArgs(soa, obj, mid, args);
}
static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(obj);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args);
}
@@ -1450,8 +1462,8 @@
}
static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
- CHECK_NON_NULL_ARGUMENT(java_object);
- CHECK_NON_NULL_ARGUMENT(fid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_object);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
ScopedObjectAccess soa(env);
mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
@@ -1460,7 +1472,7 @@
}
static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
- CHECK_NON_NULL_ARGUMENT(fid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
ScopedObjectAccess soa(env);
mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
mirror::ArtField* f = soa.DecodeField(fid);
@@ -1468,29 +1480,29 @@
}
#define GET_PRIMITIVE_FIELD(fn, instance) \
- CHECK_NON_NULL_ARGUMENT(instance); \
- CHECK_NON_NULL_ARGUMENT(fid); \
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(instance); \
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
ScopedObjectAccess soa(env); \
mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
mirror::ArtField* f = soa.DecodeField(fid); \
return f->Get ##fn (o)
#define GET_STATIC_PRIMITIVE_FIELD(fn) \
- CHECK_NON_NULL_ARGUMENT(fid); \
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
ScopedObjectAccess soa(env); \
mirror::ArtField* f = soa.DecodeField(fid); \
return f->Get ##fn (f->GetDeclaringClass())
#define SET_PRIMITIVE_FIELD(fn, instance, value) \
- CHECK_NON_NULL_ARGUMENT(instance); \
- CHECK_NON_NULL_ARGUMENT(fid); \
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(instance); \
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
ScopedObjectAccess soa(env); \
mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
mirror::ArtField* f = soa.DecodeField(fid); \
f->Set ##fn <false>(o, value)
#define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
- CHECK_NON_NULL_ARGUMENT(fid); \
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
ScopedObjectAccess soa(env); \
mirror::ArtField* f = soa.DecodeField(fid); \
f->Set ##fn <false>(f->GetDeclaringClass(), value)
@@ -1651,7 +1663,7 @@
static jboolean CallStaticBooleanMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1659,13 +1671,13 @@
}
static jboolean CallStaticBooleanMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetZ();
}
static jboolean CallStaticBooleanMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetZ();
}
@@ -1673,7 +1685,7 @@
static jbyte CallStaticByteMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1681,13 +1693,13 @@
}
static jbyte CallStaticByteMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetB();
}
static jbyte CallStaticByteMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetB();
}
@@ -1695,7 +1707,7 @@
static jchar CallStaticCharMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1703,13 +1715,13 @@
}
static jchar CallStaticCharMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetC();
}
static jchar CallStaticCharMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetC();
}
@@ -1717,7 +1729,7 @@
static jshort CallStaticShortMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1725,13 +1737,13 @@
}
static jshort CallStaticShortMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetS();
}
static jshort CallStaticShortMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetS();
}
@@ -1739,7 +1751,7 @@
static jint CallStaticIntMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1747,13 +1759,13 @@
}
static jint CallStaticIntMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetI();
}
static jint CallStaticIntMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetI();
}
@@ -1761,7 +1773,7 @@
static jlong CallStaticLongMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1769,13 +1781,13 @@
}
static jlong CallStaticLongMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetJ();
}
static jlong CallStaticLongMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetJ();
}
@@ -1783,7 +1795,7 @@
static jfloat CallStaticFloatMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1791,13 +1803,13 @@
}
static jfloat CallStaticFloatMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetF();
}
static jfloat CallStaticFloatMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetF();
}
@@ -1805,7 +1817,7 @@
static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
va_end(ap);
@@ -1813,13 +1825,13 @@
}
static jdouble CallStaticDoubleMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithVarArgs(soa, nullptr, mid, args).GetD();
}
static jdouble CallStaticDoubleMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid);
ScopedObjectAccess soa(env);
return InvokeWithJValues(soa, nullptr, mid, args).GetD();
}
@@ -1827,20 +1839,20 @@
static void CallStaticVoidMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
va_list ap;
va_start(ap, mid);
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeWithVarArgs(soa, nullptr, mid, ap);
va_end(ap);
}
static void CallStaticVoidMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeWithVarArgs(soa, nullptr, mid, args);
}
static void CallStaticVoidMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
- CHECK_NON_NULL_ARGUMENT(mid);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid);
ScopedObjectAccess soa(env);
InvokeWithJValues(soa, nullptr, mid, args);
}
@@ -1869,20 +1881,20 @@
}
static jsize GetStringLength(JNIEnv* env, jstring java_string) {
- CHECK_NON_NULL_ARGUMENT(java_string);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string);
ScopedObjectAccess soa(env);
return soa.Decode<mirror::String*>(java_string)->GetLength();
}
static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
- CHECK_NON_NULL_ARGUMENT(java_string);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string);
ScopedObjectAccess soa(env);
return soa.Decode<mirror::String*>(java_string)->GetUtfLength();
}
static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
jchar* buf) {
- CHECK_NON_NULL_ARGUMENT(java_string);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
ScopedObjectAccess soa(env);
mirror::String* s = soa.Decode<mirror::String*>(java_string);
if (start < 0 || length < 0 || start + length > s->GetLength()) {
@@ -1896,7 +1908,7 @@
static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
char* buf) {
- CHECK_NON_NULL_ARGUMENT(java_string);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
ScopedObjectAccess soa(env);
mirror::String* s = soa.Decode<mirror::String*>(java_string);
if (start < 0 || length < 0 || start + length > s->GetLength()) {
@@ -1928,7 +1940,7 @@
}
static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar* chars) {
- CHECK_NON_NULL_ARGUMENT(java_string);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
delete[] chars;
ScopedObjectAccess soa(env);
UnpinPrimitiveArray(soa, soa.Decode<mirror::String*>(java_string)->GetCharArray());
@@ -1965,7 +1977,7 @@
}
static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
- CHECK_NON_NULL_ARGUMENT(java_array);
+ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_array);
ScopedObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(java_array);
if (UNLIKELY(!obj->IsArrayInstance())) {
@@ -1985,7 +1997,7 @@
static void SetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index,
jobject java_value) {
- CHECK_NON_NULL_ARGUMENT(java_array);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
ScopedObjectAccess soa(env);
mirror::ObjectArray<mirror::Object>* array =
soa.Decode<mirror::ObjectArray<mirror::Object>*>(java_array);
@@ -1994,38 +2006,31 @@
}
static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jbooleanArray, mirror::BooleanArray>(soa, length);
+ return NewPrimitiveArray<jbooleanArray, mirror::BooleanArray>(env, length);
}
static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jbyteArray, mirror::ByteArray>(soa, length);
+ return NewPrimitiveArray<jbyteArray, mirror::ByteArray>(env, length);
}
static jcharArray NewCharArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jcharArray, mirror::CharArray>(soa, length);
+ return NewPrimitiveArray<jcharArray, mirror::CharArray>(env, length);
}
static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jdoubleArray, mirror::DoubleArray>(soa, length);
+ return NewPrimitiveArray<jdoubleArray, mirror::DoubleArray>(env, length);
}
static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jfloatArray, mirror::FloatArray>(soa, length);
+ return NewPrimitiveArray<jfloatArray, mirror::FloatArray>(env, length);
}
static jintArray NewIntArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jintArray, mirror::IntArray>(soa, length);
+ return NewPrimitiveArray<jintArray, mirror::IntArray>(env, length);
}
static jlongArray NewLongArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jlongArray, mirror::LongArray>(soa, length);
+ return NewPrimitiveArray<jlongArray, mirror::LongArray>(env, length);
}
static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass,
@@ -2034,6 +2039,7 @@
JniAbortF("NewObjectArray", "negative array length: %d", length);
return nullptr;
}
+ CHECK_NON_NULL_ARGUMENT(element_jclass);
// Compute the array class corresponding to the given element class.
ScopedObjectAccess soa(env);
@@ -2075,14 +2081,18 @@
}
static jshortArray NewShortArray(JNIEnv* env, jsize length) {
- ScopedObjectAccess soa(env);
- return NewPrimitiveArray<jshortArray, mirror::ShortArray>(soa, length);
+ return NewPrimitiveArray<jshortArray, mirror::ShortArray>(env, length);
}
static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray java_array, jboolean* is_copy) {
CHECK_NON_NULL_ARGUMENT(java_array);
ScopedObjectAccess soa(env);
mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
+ if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) {
+ JniAbortF("GetPrimitiveArrayCritical", "expected primitive array, given %s",
+ PrettyDescriptor(array->GetClass()).c_str());
+ return nullptr;
+ }
gc::Heap* heap = Runtime::Current()->GetHeap();
if (heap->IsMovableObject(array)) {
heap->IncrementDisableMovingGC(soa.Self());
@@ -2096,196 +2106,174 @@
return array->GetRawData(array->GetClass()->GetComponentSize(), 0);
}
- static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* elements, jint mode) {
- CHECK_NON_NULL_ARGUMENT(array);
- ReleasePrimitiveArray(env, array, elements, mode);
+ static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray java_array, void* elements,
+ jint mode) {
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
+ ScopedObjectAccess soa(env);
+ mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
+ if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) {
+ JniAbortF("ReleasePrimitiveArrayCritical", "expected primitive array, given %s",
+ PrettyDescriptor(array->GetClass()).c_str());
+ return;
+ }
+ const size_t component_size = array->GetClass()->GetComponentSize();
+ ReleasePrimitiveArray(soa, array, component_size, elements, mode);
}
static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jbooleanArray, jboolean*, mirror::BooleanArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, is_copy);
}
static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jbyteArray, jbyte*, mirror::ByteArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jbyteArray, jbyte, mirror::ByteArray>(env, array, is_copy);
}
static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jcharArray, jchar*, mirror::CharArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jcharArray, jchar, mirror::CharArray>(env, array, is_copy);
}
static jdouble* GetDoubleArrayElements(JNIEnv* env, jdoubleArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jdoubleArray, jdouble*, mirror::DoubleArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, is_copy);
}
static jfloat* GetFloatArrayElements(JNIEnv* env, jfloatArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jfloatArray, jfloat*, mirror::FloatArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jfloatArray, jfloat, mirror::FloatArray>(env, array, is_copy);
}
static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jintArray, jint*, mirror::IntArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jintArray, jint, mirror::IntArray>(env, array, is_copy);
}
static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jlongArray, jlong*, mirror::LongArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jlongArray, jlong, mirror::LongArray>(env, array, is_copy);
}
static jshort* GetShortArrayElements(JNIEnv* env, jshortArray array, jboolean* is_copy) {
- CHECK_NON_NULL_ARGUMENT(array);
- ScopedObjectAccess soa(env);
- return GetPrimitiveArray<jshortArray, jshort*, mirror::ShortArray>(soa, array, is_copy);
+ return GetPrimitiveArray<jshortArray, jshort, mirror::ShortArray>(env, array, is_copy);
}
static void ReleaseBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* elements,
jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, elements,
+ mode);
}
static void ReleaseByteArrayElements(JNIEnv* env, jbyteArray array, jbyte* elements, jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jbyteArray, jbyte, mirror::ByteArray>(env, array, elements, mode);
}
static void ReleaseCharArrayElements(JNIEnv* env, jcharArray array, jchar* elements, jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jcharArray, jchar, mirror::CharArray>(env, array, elements, mode);
}
static void ReleaseDoubleArrayElements(JNIEnv* env, jdoubleArray array, jdouble* elements,
jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, elements, mode);
}
static void ReleaseFloatArrayElements(JNIEnv* env, jfloatArray array, jfloat* elements,
jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jfloatArray, jfloat, mirror::FloatArray>(env, array, elements, mode);
}
static void ReleaseIntArrayElements(JNIEnv* env, jintArray array, jint* elements, jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jintArray, jint, mirror::IntArray>(env, array, elements, mode);
}
static void ReleaseLongArrayElements(JNIEnv* env, jlongArray array, jlong* elements, jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jlongArray, jlong, mirror::LongArray>(env, array, elements, mode);
}
static void ReleaseShortArrayElements(JNIEnv* env, jshortArray array, jshort* elements,
jint mode) {
- ReleasePrimitiveArray(env, array, elements, mode);
+ ReleasePrimitiveArray<jshortArray, jshort, mirror::ShortArray>(env, array, elements, mode);
}
static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
jboolean* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(soa, array, start,
+ GetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, start,
length, buf);
}
static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
jbyte* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(soa, array, start, length, buf);
+ GetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(env, array, start, length, buf);
}
static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
jchar* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(soa, array, start, length, buf);
+ GetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(env, array, start, length, buf);
}
static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
jdouble* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(soa, array, start, length,
+ GetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, start, length,
buf);
}
static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
jfloat* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(soa, array, start, length,
+ GetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(env, array, start, length,
buf);
}
static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
jint* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(soa, array, start, length, buf);
+ GetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(env, array, start, length, buf);
}
static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
jlong* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(soa, array, start, length, buf);
+ GetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(env, array, start, length, buf);
}
static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
jshort* buf) {
- ScopedObjectAccess soa(env);
- GetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(soa, array, start, length,
+ GetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(env, array, start, length,
buf);
}
static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
const jboolean* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(soa, array, start,
+ SetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, start,
length, buf);
}
static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
const jbyte* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(soa, array, start, length, buf);
+ SetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(env, array, start, length, buf);
}
static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
const jchar* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(soa, array, start, length, buf);
+ SetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(env, array, start, length, buf);
}
static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
const jdouble* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(soa, array, start, length,
+ SetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, start, length,
buf);
}
static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
const jfloat* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(soa, array, start, length,
+ SetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(env, array, start, length,
buf);
}
static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
const jint* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(soa, array, start, length, buf);
+ SetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(env, array, start, length, buf);
}
static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
const jlong* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(soa, array, start, length, buf);
+ SetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(env, array, start, length, buf);
}
static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
const jshort* buf) {
- ScopedObjectAccess soa(env);
- SetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(soa, array, start, length,
+ SetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(env, array, start, length,
buf);
}
@@ -2300,7 +2288,7 @@
JniAbortF("RegisterNatives", "negative method count: %d", method_count);
return JNI_ERR; // Not reached.
}
- CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class);
+ CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class, JNI_ERR);
ScopedObjectAccess soa(env);
mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
if (UNLIKELY(method_count == 0)) {
@@ -2308,7 +2296,7 @@
<< PrettyDescriptor(c);
return JNI_OK;
}
- CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods);
+ CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods, JNI_ERR);
for (jint i = 0; i < method_count; ++i) {
const char* name = methods[i].name;
const char* sig = methods[i].signature;
@@ -2345,30 +2333,37 @@
}
static jint UnregisterNatives(JNIEnv* env, jclass java_class) {
- CHECK_NON_NULL_ARGUMENT(java_class);
+ CHECK_NON_NULL_ARGUMENT_RETURN(java_class, JNI_ERR);
ScopedObjectAccess soa(env);
mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
+ size_t unregistered_count = 0;
for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
mirror::ArtMethod* m = c->GetDirectMethod(i);
if (m->IsNative()) {
m->UnregisterNative(soa.Self());
+ unregistered_count++;
}
}
for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
mirror::ArtMethod* m = c->GetVirtualMethod(i);
if (m->IsNative()) {
m->UnregisterNative(soa.Self());
+ unregistered_count++;
}
}
+ if (unregistered_count == 0) {
+ LOG(WARNING) << "JNI UnregisterNatives: attempt to unregister native methods of class '"
+ << PrettyDescriptor(c) << "' that contains no native methods";
+ }
return JNI_OK;
}
static jint MonitorEnter(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
- CHECK_NON_NULL_ARGUMENT(java_object);
+ CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR);
ScopedObjectAccess soa(env);
mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
o = o->MonitorEnter(soa.Self());
@@ -2380,7 +2375,7 @@
}
static jint MonitorExit(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
- CHECK_NON_NULL_ARGUMENT(java_object);
+ CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR);
ScopedObjectAccess soa(env);
mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
o->MonitorExit(soa.Self());
@@ -2392,7 +2387,7 @@
}
static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
- CHECK_NON_NULL_ARGUMENT(vm);
+ CHECK_NON_NULL_ARGUMENT_RETURN(vm, JNI_ERR);
Runtime* runtime = Runtime::Current();
if (runtime != nullptr) {
*vm = runtime->GetJavaVM();
@@ -2432,7 +2427,7 @@
}
static jobjectRefType GetObjectRefType(JNIEnv* env, jobject java_object) {
- CHECK_NON_NULL_ARGUMENT(java_object);
+ CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNIInvalidRefType);
// Do we definitely know what kind of reference this is?
IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
@@ -2479,51 +2474,82 @@
}
template<typename JniT, typename ArtT>
- static JniT NewPrimitiveArray(const ScopedObjectAccess& soa, jsize length)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ static JniT NewPrimitiveArray(JNIEnv* env, jsize length) {
if (UNLIKELY(length < 0)) {
JniAbortF("NewPrimitiveArray", "negative array length: %d", length);
return nullptr;
}
+ ScopedObjectAccess soa(env);
ArtT* result = ArtT::Alloc(soa.Self(), length);
return soa.AddLocalReference<JniT>(result);
}
- template <typename ArrayT, typename CArrayT, typename ArtArrayT>
- static CArrayT GetPrimitiveArray(ScopedObjectAccess& soa, ArrayT java_array,
- jboolean* is_copy)
+ template <typename JArrayT, typename ElementT, typename ArtArrayT>
+ static ArtArrayT* DecodeAndCheckArrayType(ScopedObjectAccess& soa, JArrayT java_array,
+ const char* fn_name, const char* operation)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ArtArrayT* array = soa.Decode<ArtArrayT*>(java_array);
+ if (UNLIKELY(ArtArrayT::GetArrayClass() != array->GetClass())) {
+ JniAbortF(fn_name, "attempt to %s %s primitive array elements with an object of type %s",
+ operation, PrettyDescriptor(ArtArrayT::GetArrayClass()->GetComponentType()).c_str(),
+ PrettyDescriptor(array->GetClass()).c_str());
+ return nullptr;
+ }
+ DCHECK_EQ(sizeof(ElementT), array->GetClass()->GetComponentSize());
+ return array;
+ }
+
+ template <typename ArrayT, typename ElementT, typename ArtArrayT>
+ static ElementT* GetPrimitiveArray(JNIEnv* env, ArrayT java_array, jboolean* is_copy) {
+ CHECK_NON_NULL_ARGUMENT(java_array);
+ ScopedObjectAccess soa(env);
+ ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
+ "GetArrayElements",
+ "get");
+ if (UNLIKELY(array == nullptr)) {
+ return nullptr;
+ }
PinPrimitiveArray(soa, array);
// Only make a copy if necessary.
if (Runtime::Current()->GetHeap()->IsMovableObject(array)) {
if (is_copy != nullptr) {
*is_copy = JNI_TRUE;
}
- static const size_t component_size = array->GetClass()->GetComponentSize();
+ const size_t component_size = sizeof(ElementT);
size_t size = array->GetLength() * component_size;
void* data = new uint64_t[RoundUp(size, 8) / 8];
memcpy(data, array->GetData(), size);
- return reinterpret_cast<CArrayT>(data);
+ return reinterpret_cast<ElementT*>(data);
} else {
if (is_copy != nullptr) {
*is_copy = JNI_FALSE;
}
- return reinterpret_cast<CArrayT>(array->GetData());
+ return reinterpret_cast<ElementT*>(array->GetData());
}
}
- template <typename ArrayT, typename ElementT>
+ template <typename ArrayT, typename ElementT, typename ArtArrayT>
static void ReleasePrimitiveArray(JNIEnv* env, ArrayT java_array, ElementT* elements, jint mode) {
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
ScopedObjectAccess soa(env);
- mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
- size_t component_size = array->GetClass()->GetComponentSize();
+ ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array,
+ "ReleaseArrayElements",
+ "release");
+ if (array == nullptr) {
+ return;
+ }
+ ReleasePrimitiveArray(soa, array, sizeof(ElementT), elements, mode);
+ }
+
+ static void ReleasePrimitiveArray(ScopedObjectAccess& soa, mirror::Array* array,
+ size_t component_size, void* elements, jint mode)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
void* array_data = array->GetRawData(component_size, 0);
gc::Heap* heap = Runtime::Current()->GetHeap();
- bool is_copy = array_data != reinterpret_cast<void*>(elements);
+ bool is_copy = array_data != elements;
size_t bytes = array->GetLength() * component_size;
- VLOG(heap) << "Release primitive array " << env << " array_data " << array_data
- << " elements " << reinterpret_cast<void*>(elements);
+ VLOG(heap) << "Release primitive array " << soa.Env() << " array_data " << array_data
+ << " elements " << elements;
if (is_copy) {
// Sanity check: If elements is not the same as the java array's data, it better not be a
// heap address. TODO: This might be slow to check, may be worth keeping track of which
@@ -2549,33 +2575,43 @@
}
}
- template <typename JavaArrayT, typename JavaT, typename ArrayT>
- static void GetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
- jsize start, jsize length, JavaT* buf)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK_NON_NULL_ARGUMENT(java_array);
- ArrayT* array = soa.Decode<ArrayT*>(java_array);
- if (start < 0 || length < 0 || start + length > array->GetLength()) {
- ThrowAIOOBE(soa, array, start, length, "src");
- } else {
- CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
- JavaT* data = array->GetData();
- memcpy(buf, data + start, length * sizeof(JavaT));
+ template <typename JArrayT, typename ElementT, typename ArtArrayT>
+ static void GetPrimitiveArrayRegion(JNIEnv* env, JArrayT java_array,
+ jsize start, jsize length, ElementT* buf) {
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
+ ScopedObjectAccess soa(env);
+ ArtArrayT* array =
+ DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
+ "GetPrimitiveArrayRegion",
+ "get region of");
+ if (array != nullptr) {
+ if (start < 0 || length < 0 || start + length > array->GetLength()) {
+ ThrowAIOOBE(soa, array, start, length, "src");
+ } else {
+ CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
+ ElementT* data = array->GetData();
+ memcpy(buf, data + start, length * sizeof(ElementT));
+ }
}
}
- template <typename JavaArrayT, typename JavaT, typename ArrayT>
- static void SetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
- jsize start, jsize length, const JavaT* buf)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK_NON_NULL_ARGUMENT(java_array);
- ArrayT* array = soa.Decode<ArrayT*>(java_array);
- if (start < 0 || length < 0 || start + length > array->GetLength()) {
- ThrowAIOOBE(soa, array, start, length, "dst");
- } else {
- CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
- JavaT* data = array->GetData();
- memcpy(data + start, buf, length * sizeof(JavaT));
+ template <typename JArrayT, typename ElementT, typename ArtArrayT>
+ static void SetPrimitiveArrayRegion(JNIEnv* env, JArrayT java_array,
+ jsize start, jsize length, const ElementT* buf) {
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array);
+ ScopedObjectAccess soa(env);
+ ArtArrayT* array =
+ DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array,
+ "SetPrimitiveArrayRegion",
+ "set region of");
+ if (array != nullptr) {
+ if (start < 0 || length < 0 || start + length > array->GetLength()) {
+ ThrowAIOOBE(soa, array, start, length, "dst");
+ } else {
+ CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
+ ElementT* data = array->GetData();
+ memcpy(data + start, buf, length * sizeof(ElementT));
+ }
}
}
};
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 778b9e5..83e9b10 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -33,35 +33,54 @@
// Turn on -verbose:jni for the JNI tests.
// gLogVerbosity.jni = true;
- vm_->AttachCurrentThread(&env_, NULL);
+ vm_->AttachCurrentThread(&env_, nullptr);
ScopedLocalRef<jclass> aioobe(env_,
env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
- CHECK(aioobe.get() != NULL);
+ CHECK(aioobe.get() != nullptr);
aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
- CHECK(ase.get() != NULL);
+ CHECK(ase.get() != nullptr);
ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
ScopedLocalRef<jclass> sioobe(env_,
env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
- CHECK(sioobe.get() != NULL);
+ CHECK(sioobe.get() != nullptr);
sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
}
+ void ExpectException(jclass exception_class) {
+ EXPECT_TRUE(env_->ExceptionCheck());
+ jthrowable exception = env_->ExceptionOccurred();
+ EXPECT_NE(nullptr, exception);
+ env_->ExceptionClear();
+ EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class));
+ }
+
+ void ExpectClassFound(const char* name) {
+ EXPECT_NE(env_->FindClass(name), nullptr) << name;
+ EXPECT_FALSE(env_->ExceptionCheck()) << name;
+ }
+
+ void ExpectClassNotFound(const char* name) {
+ EXPECT_EQ(env_->FindClass(name), nullptr) << name;
+ EXPECT_TRUE(env_->ExceptionCheck()) << name;
+ env_->ExceptionClear();
+ }
+
void CleanUpJniEnv() {
- if (aioobe_ != NULL) {
+ if (aioobe_ != nullptr) {
env_->DeleteGlobalRef(aioobe_);
- aioobe_ = NULL;
+ aioobe_ = nullptr;
}
- if (ase_ != NULL) {
+ if (ase_ != nullptr) {
env_->DeleteGlobalRef(ase_);
- ase_ = NULL;
+ ase_ = nullptr;
}
- if (sioobe_ != NULL) {
+ if (sioobe_ != nullptr) {
env_->DeleteGlobalRef(sioobe_);
- sioobe_ = NULL;
+ sioobe_ = nullptr;
}
}
@@ -86,9 +105,9 @@
TEST_F(JniInternalTest, AllocObject) {
jclass c = env_->FindClass("java/lang/String");
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
jobject o = env_->AllocObject(c);
- ASSERT_TRUE(o != NULL);
+ ASSERT_NE(o, nullptr);
// We have an instance of the class we asked for...
ASSERT_TRUE(env_->IsInstanceOf(o, c));
@@ -96,139 +115,152 @@
// we didn't call a constructor.
ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
- ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL);
+ ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == nullptr);
}
TEST_F(JniInternalTest, GetVersion) {
ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
}
-#define EXPECT_CLASS_FOUND(NAME) \
- EXPECT_TRUE(env_->FindClass(NAME) != NULL); \
- EXPECT_FALSE(env_->ExceptionCheck())
-
-#define EXPECT_CLASS_NOT_FOUND(NAME) \
- EXPECT_TRUE(env_->FindClass(NAME) == NULL); \
- EXPECT_TRUE(env_->ExceptionCheck()); \
- env_->ExceptionClear()
-
TEST_F(JniInternalTest, FindClass) {
// Reference types...
- EXPECT_CLASS_FOUND("java/lang/String");
+ ExpectClassFound("java/lang/String");
// ...for arrays too, where you must include "L;".
- EXPECT_CLASS_FOUND("[Ljava/lang/String;");
+ ExpectClassFound("[Ljava/lang/String;");
// Primitive arrays are okay too, if the primitive type is valid.
- EXPECT_CLASS_FOUND("[C");
+ ExpectClassFound("[C");
{
- // We support . as well as / for compatibility, if -Xcheck:jni is off.
CheckJniAbortCatcher check_jni_abort_catcher;
- EXPECT_CLASS_FOUND("java.lang.String");
+ env_->FindClass(nullptr);
+ check_jni_abort_catcher.Check("name == null");
+
+ // We support . as well as / for compatibility, if -Xcheck:jni is off.
+ ExpectClassFound("java.lang.String");
check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
- EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;");
+ ExpectClassNotFound("Ljava.lang.String;");
check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'");
- EXPECT_CLASS_FOUND("[Ljava.lang.String;");
+ ExpectClassFound("[Ljava.lang.String;");
check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
- EXPECT_CLASS_NOT_FOUND("[java.lang.String");
+ ExpectClassNotFound("[java.lang.String");
check_jni_abort_catcher.Check("illegal class name '[java.lang.String'");
// You can't include the "L;" in a JNI class descriptor.
- EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;");
+ ExpectClassNotFound("Ljava/lang/String;");
check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'");
// But you must include it for an array of any reference type.
- EXPECT_CLASS_NOT_FOUND("[java/lang/String");
+ ExpectClassNotFound("[java/lang/String");
check_jni_abort_catcher.Check("illegal class name '[java/lang/String'");
- EXPECT_CLASS_NOT_FOUND("[K");
+ ExpectClassNotFound("[K");
check_jni_abort_catcher.Check("illegal class name '[K'");
+
+ // Void arrays aren't allowed.
+ ExpectClassNotFound("[V");
+ check_jni_abort_catcher.Check("illegal class name '[V'");
}
// But primitive types aren't allowed...
- EXPECT_CLASS_NOT_FOUND("C");
- EXPECT_CLASS_NOT_FOUND("K");
+ ExpectClassNotFound("C");
+ ExpectClassNotFound("V");
+ ExpectClassNotFound("K");
}
-#define EXPECT_EXCEPTION(exception_class) \
- do { \
- EXPECT_TRUE(env_->ExceptionCheck()); \
- jthrowable exception = env_->ExceptionOccurred(); \
- EXPECT_NE(static_cast<jthrowable>(NULL), exception); \
- env_->ExceptionClear(); \
- EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); \
- } while (false)
-
TEST_F(JniInternalTest, GetFieldID) {
jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
- ASSERT_TRUE(jlnsfe != NULL);
+ ASSERT_NE(jlnsfe, nullptr);
jclass c = env_->FindClass("java/lang/String");
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
// Wrong type.
jfieldID fid = env_->GetFieldID(c, "count", "J");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
// Wrong type where type doesn't exist.
fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
// Wrong name.
fid = env_->GetFieldID(c, "Count", "I");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
// Good declared field lookup.
fid = env_->GetFieldID(c, "count", "I");
- EXPECT_NE(static_cast<jfieldID>(NULL), fid);
- EXPECT_TRUE(fid != NULL);
+ EXPECT_NE(nullptr, fid);
EXPECT_FALSE(env_->ExceptionCheck());
// Good superclass field lookup.
c = env_->FindClass("java/lang/StringBuilder");
fid = env_->GetFieldID(c, "count", "I");
- EXPECT_NE(static_cast<jfieldID>(NULL), fid);
- EXPECT_TRUE(fid != NULL);
+ EXPECT_NE(nullptr, fid);
+ EXPECT_NE(fid, nullptr);
EXPECT_FALSE(env_->ExceptionCheck());
// Not instance.
fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
+
+ // Bad arguments.
+ CheckJniAbortCatcher check_jni_abort_catcher;
+ fid = env_->GetFieldID(nullptr, "count", "I");
+ EXPECT_EQ(nullptr, fid);
+ check_jni_abort_catcher.Check("java_class == null");
+ fid = env_->GetFieldID(c, nullptr, "I");
+ EXPECT_EQ(nullptr, fid);
+ check_jni_abort_catcher.Check("name == null");
+ fid = env_->GetFieldID(c, "count", nullptr);
+ EXPECT_EQ(nullptr, fid);
+ check_jni_abort_catcher.Check("sig == null");
}
TEST_F(JniInternalTest, GetStaticFieldID) {
jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
- ASSERT_TRUE(jlnsfe != NULL);
+ ASSERT_NE(jlnsfe, nullptr);
jclass c = env_->FindClass("java/lang/String");
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
// Wrong type.
jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
// Wrong type where type doesn't exist.
fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
// Wrong name.
fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
// Good declared field lookup.
fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- EXPECT_NE(static_cast<jfieldID>(NULL), fid);
- EXPECT_TRUE(fid != NULL);
+ EXPECT_NE(nullptr, fid);
+ EXPECT_NE(fid, nullptr);
EXPECT_FALSE(env_->ExceptionCheck());
// Not static.
fid = env_->GetStaticFieldID(c, "count", "I");
- EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
- EXPECT_EXCEPTION(jlnsfe);
+ EXPECT_EQ(nullptr, fid);
+ ExpectException(jlnsfe);
+
+ // Bad arguments.
+ CheckJniAbortCatcher check_jni_abort_catcher;
+ fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
+ EXPECT_EQ(nullptr, fid);
+ check_jni_abort_catcher.Check("java_class == null");
+ fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;");
+ EXPECT_EQ(nullptr, fid);
+ check_jni_abort_catcher.Check("name == null");
+ fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr);
+ EXPECT_EQ(nullptr, fid);
+ check_jni_abort_catcher.Check("sig == null");
}
TEST_F(JniInternalTest, GetMethodID) {
@@ -242,24 +274,36 @@
// Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
// a pending exception
jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
- EXPECT_EQ(static_cast<jmethodID>(NULL), method);
- EXPECT_EXCEPTION(jlnsme);
+ EXPECT_EQ(nullptr, method);
+ ExpectException(jlnsme);
// Check that java.lang.Object.equals() does exist
method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
- EXPECT_NE(static_cast<jmethodID>(NULL), method);
+ EXPECT_NE(nullptr, method);
EXPECT_FALSE(env_->ExceptionCheck());
// Check that GetMethodID for java.lang.String.valueOf(int) fails as the
// method is static
method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
- EXPECT_EQ(static_cast<jmethodID>(NULL), method);
- EXPECT_EXCEPTION(jlnsme);
+ EXPECT_EQ(nullptr, method);
+ ExpectException(jlnsme);
// Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor
method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
- EXPECT_NE(static_cast<jmethodID>(NULL), method);
+ EXPECT_NE(nullptr, method);
EXPECT_FALSE(env_->ExceptionCheck());
+
+ // Bad arguments.
+ CheckJniAbortCatcher check_jni_abort_catcher;
+ method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V");
+ EXPECT_EQ(nullptr, method);
+ check_jni_abort_catcher.Check("java_class == null");
+ method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V");
+ EXPECT_EQ(nullptr, method);
+ check_jni_abort_catcher.Check("name == null");
+ method = env_->GetMethodID(jlnsme, "<init>", nullptr);
+ EXPECT_EQ(nullptr, method);
+ check_jni_abort_catcher.Check("sig == null");
}
TEST_F(JniInternalTest, GetStaticMethodID) {
@@ -272,93 +316,155 @@
// Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
// a pending exception
jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
- EXPECT_EQ(static_cast<jmethodID>(NULL), method);
- EXPECT_EXCEPTION(jlnsme);
+ EXPECT_EQ(nullptr, method);
+ ExpectException(jlnsme);
// Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
// the method is not static
method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
- EXPECT_EQ(static_cast<jmethodID>(NULL), method);
- EXPECT_EXCEPTION(jlnsme);
+ EXPECT_EQ(nullptr, method);
+ ExpectException(jlnsme);
// Check that java.lang.String.valueOf(int) does exist
jclass jlstring = env_->FindClass("java/lang/String");
- method = env_->GetStaticMethodID(jlstring, "valueOf",
- "(I)Ljava/lang/String;");
- EXPECT_NE(static_cast<jmethodID>(NULL), method);
+ method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
+ EXPECT_NE(nullptr, method);
EXPECT_FALSE(env_->ExceptionCheck());
+
+ // Bad arguments.
+ CheckJniAbortCatcher check_jni_abort_catcher;
+ method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;");
+ EXPECT_EQ(nullptr, method);
+ check_jni_abort_catcher.Check("java_class == null");
+ method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;");
+ EXPECT_EQ(nullptr, method);
+ check_jni_abort_catcher.Check("name == null");
+ method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr);
+ EXPECT_EQ(nullptr, method);
+ check_jni_abort_catcher.Check("sig == null");
}
TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
jclass jlrField = env_->FindClass("java/lang/reflect/Field");
jclass c = env_->FindClass("java/lang/String");
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
jfieldID fid = env_->GetFieldID(c, "count", "I");
- ASSERT_TRUE(fid != NULL);
+ ASSERT_NE(fid, nullptr);
// Turn the fid into a java.lang.reflect.Field...
jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
// ...and back again.
jfieldID fid2 = env_->FromReflectedField(field);
- ASSERT_TRUE(fid2 != NULL);
+ ASSERT_NE(fid2, nullptr);
// Make sure we can actually use it.
jstring s = env_->NewStringUTF("poop");
ASSERT_EQ(4, env_->GetIntField(s, fid2));
+
+ // Bad arguments.
+ CheckJniAbortCatcher check_jni_abort_catcher;
+ field = env_->ToReflectedField(c, nullptr, JNI_FALSE);
+ EXPECT_EQ(field, nullptr);
+ check_jni_abort_catcher.Check("fid == null");
+ fid2 = env_->FromReflectedField(nullptr);
+ ASSERT_EQ(fid2, nullptr);
+ check_jni_abort_catcher.Check("jlr_field == null");
}
TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
jclass c = env_->FindClass("java/lang/String");
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
jmethodID mid = env_->GetMethodID(c, "length", "()I");
- ASSERT_TRUE(mid != NULL);
+ ASSERT_NE(mid, nullptr);
// Turn the mid into a java.lang.reflect.Method...
jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
// ...and back again.
jmethodID mid2 = env_->FromReflectedMethod(method);
- ASSERT_TRUE(mid2 != NULL);
+ ASSERT_NE(mid2, nullptr);
// Make sure we can actually use it.
jstring s = env_->NewStringUTF("poop");
ASSERT_EQ(4, env_->CallIntMethod(s, mid2));
+
+ // Bad arguments.
+ CheckJniAbortCatcher check_jni_abort_catcher;
+ method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE);
+ EXPECT_EQ(method, nullptr);
+ check_jni_abort_catcher.Check("mid == null");
+ mid2 = env_->FromReflectedMethod(method);
+ ASSERT_EQ(mid2, nullptr);
+ check_jni_abort_catcher.Check("jlr_method == null");
}
-void BogusMethod() {
- // You can't pass NULL function pointers to RegisterNatives.
+static void BogusMethod() {
+ // You can't pass nullptr function pointers to RegisterNatives.
}
-TEST_F(JniInternalTest, RegisterNatives) {
+TEST_F(JniInternalTest, RegisterAndUnregisterNatives) {
jclass jlobject = env_->FindClass("java/lang/Object");
jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
- // Sanity check that no exceptions are pending
+ // Sanity check that no exceptions are pending.
ASSERT_FALSE(env_->ExceptionCheck());
- // Check that registering to a non-existent java.lang.Object.foo() causes a
- // NoSuchMethodError
+ // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError.
{
- JNINativeMethod methods[] = { { "foo", "()V", NULL } };
- env_->RegisterNatives(jlobject, methods, 1);
+ JNINativeMethod methods[] = { { "foo", "()V", nullptr } };
+ EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
}
- EXPECT_EXCEPTION(jlnsme);
+ ExpectException(jlnsme);
- // Check that registering non-native methods causes a NoSuchMethodError
+ // Check that registering non-native methods causes a NoSuchMethodError.
{
- JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", NULL } };
- env_->RegisterNatives(jlobject, methods, 1);
+ JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", nullptr } };
+ EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
}
- EXPECT_EXCEPTION(jlnsme);
+ ExpectException(jlnsme);
- // Check that registering native methods is successful
+ // Check that registering native methods is successful.
{
JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } };
- env_->RegisterNatives(jlobject, methods, 1);
+ EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK);
+ }
+ EXPECT_FALSE(env_->ExceptionCheck());
+ EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
+
+ // Check that registering no methods isn't a failure.
+ {
+ JNINativeMethod methods[] = { };
+ EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK);
+ }
+ EXPECT_FALSE(env_->ExceptionCheck());
+ EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
+
+ // Check that registering a -ve number of methods is a failure.
+ CheckJniAbortCatcher check_jni_abort_catcher;
+ for (int i = -10; i < 0; ++i) {
+ JNINativeMethod methods[] = { };
+ EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR);
+ check_jni_abort_catcher.Check("negative method count: ");
}
EXPECT_FALSE(env_->ExceptionCheck());
- env_->UnregisterNatives(jlobject);
+ // Passing a class of null is a failure.
+ {
+ JNINativeMethod methods[] = { };
+ EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR);
+ check_jni_abort_catcher.Check("java_class == null");
+ }
+
+ // Passing methods as null is a failure.
+ EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR);
+ check_jni_abort_catcher.Check("methods == null");
+
+ // Unregisters null is a failure.
+ EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR);
+ check_jni_abort_catcher.Check("java_class == null");
+
+ // Unregistering a class with no natives is a warning.
+ EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK);
}
#define EXPECT_PRIMITIVE_ARRAY(new_fn, \
@@ -368,52 +474,69 @@
release_elements_fn, \
scalar_type, \
expected_class_descriptor) \
+ jsize size = 4; \
+ \
{ \
CheckJniAbortCatcher jni_abort_catcher; \
/* Allocate an negative sized array and check it has the right failure type. */ \
- env_->new_fn(-1); \
+ EXPECT_EQ(env_->new_fn(-1), nullptr); \
jni_abort_catcher.Check("negative array length: -1"); \
- env_->new_fn(std::numeric_limits<jint>::min()); \
+ EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \
jni_abort_catcher.Check("negative array length: -2147483648"); \
+ /* Pass the array as null. */ \
+ EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \
+ jni_abort_catcher.Check("java_array == null"); \
+ env_->get_region_fn(nullptr, 0, 0, nullptr); \
+ jni_abort_catcher.Check("java_array == null"); \
+ env_->set_region_fn(nullptr, 0, 0, nullptr); \
+ jni_abort_catcher.Check("java_array == null"); \
+ env_->get_elements_fn(nullptr, nullptr); \
+ jni_abort_catcher.Check("java_array == null"); \
+ env_->release_elements_fn(nullptr, nullptr, 0); \
+ jni_abort_catcher.Check("java_array == null"); \
+ /* Pass the elements for region as null. */ \
+ scalar_type ## Array a = env_->new_fn(size); \
+ env_->get_region_fn(a, 0, size, nullptr); \
+ jni_abort_catcher.Check("buf == null"); \
+ env_->set_region_fn(a, 0, size, nullptr); \
+ jni_abort_catcher.Check("buf == null"); \
} \
- jsize size = 4; \
- \
/* Allocate an array and check it has the right type and length. */ \
scalar_type ## Array a = env_->new_fn(size); \
- EXPECT_TRUE(a != NULL); \
+ EXPECT_NE(a, nullptr); \
EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
EXPECT_EQ(size, env_->GetArrayLength(a)); \
\
/* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \
/* AIOOBE for negative start offset. */ \
- env_->get_region_fn(a, -1, 1, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
- env_->set_region_fn(a, -1, 1, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
+ env_->get_region_fn(a, -1, 1, nullptr); \
+ ExpectException(aioobe_); \
+ env_->set_region_fn(a, -1, 1, nullptr); \
+ ExpectException(aioobe_); \
\
/* AIOOBE for negative length. */ \
- env_->get_region_fn(a, 0, -1, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
- env_->set_region_fn(a, 0, -1, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
+ env_->get_region_fn(a, 0, -1, nullptr); \
+ ExpectException(aioobe_); \
+ env_->set_region_fn(a, 0, -1, nullptr); \
+ ExpectException(aioobe_); \
\
/* AIOOBE for buffer overrun. */ \
- env_->get_region_fn(a, size - 1, size, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
- env_->set_region_fn(a, size - 1, size, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
+ env_->get_region_fn(a, size - 1, size, nullptr); \
+ ExpectException(aioobe_); \
+ env_->set_region_fn(a, size - 1, size, nullptr); \
+ ExpectException(aioobe_); \
\
- /* It's okay for the buffer to be NULL as long as the length is 0. */ \
- env_->get_region_fn(a, 2, 0, NULL); \
+ /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
+ env_->get_region_fn(a, 2, 0, nullptr); \
/* Even if the offset is invalid... */ \
- env_->get_region_fn(a, 123, 0, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
+ env_->get_region_fn(a, 123, 0, nullptr); \
+ ExpectException(aioobe_); \
\
- /* It's okay for the buffer to be NULL as long as the length is 0. */ \
- env_->set_region_fn(a, 2, 0, NULL); \
+ /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
+ env_->set_region_fn(a, 2, 0, nullptr); \
/* Even if the offset is invalid... */ \
- env_->set_region_fn(a, 123, 0, NULL); \
- EXPECT_EXCEPTION(aioobe_); \
+ env_->set_region_fn(a, 123, 0, nullptr); \
+ ExpectException(aioobe_); \
\
/* Prepare a couple of buffers. */ \
UniquePtr<scalar_type[]> src_buf(new scalar_type[size]); \
@@ -437,12 +560,12 @@
EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
<< "full copy not equal"; \
/* GetPrimitiveArrayCritical */ \
- void* v = env_->GetPrimitiveArrayCritical(a, NULL); \
+ void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \
EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
<< "GetPrimitiveArrayCritical not equal"; \
env_->ReleasePrimitiveArrayCritical(a, v, 0); \
/* GetXArrayElements */ \
- scalar_type* xs = env_->get_elements_fn(a, NULL); \
+ scalar_type* xs = env_->get_elements_fn(a, nullptr); \
EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
<< # get_elements_fn " not equal"; \
env_->release_elements_fn(a, xs, 0); \
@@ -480,31 +603,206 @@
GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
}
+TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) {
+ CheckJniAbortCatcher jni_abort_catcher;
+ jbooleanArray array = env_->NewBooleanArray(10);
+ jboolean is_copy;
+ EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get byte primitive array elements with an object of type boolean[]");
+ EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get short primitive array elements with an object of type boolean[]");
+ EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get char primitive array elements with an object of type boolean[]");
+ EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get int primitive array elements with an object of type boolean[]");
+ EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get long primitive array elements with an object of type boolean[]");
+ EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get float primitive array elements with an object of type boolean[]");
+ EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get double primitive array elements with an object of type boolean[]");
+ jbyteArray array2 = env_->NewByteArray(10);
+ EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get boolean primitive array elements with an object of type byte[]");
+ jobject object = env_->NewStringUTF("Test String");
+ EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy), nullptr);
+ jni_abort_catcher.Check(
+ "attempt to get boolean primitive array elements with an object of type java.lang.String");
+}
+
+TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) {
+ CheckJniAbortCatcher jni_abort_catcher;
+ jbooleanArray array = env_->NewBooleanArray(10);
+ ASSERT_TRUE(array != nullptr);
+ jboolean is_copy;
+ jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy);
+ ASSERT_TRUE(elements != nullptr);
+ env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array),
+ reinterpret_cast<jbyte*>(elements), 0);
+ jni_abort_catcher.Check(
+ "attempt to release byte primitive array elements with an object of type boolean[]");
+ env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array),
+ reinterpret_cast<jshort*>(elements), 0);
+ jni_abort_catcher.Check(
+ "attempt to release short primitive array elements with an object of type boolean[]");
+ env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array),
+ reinterpret_cast<jchar*>(elements), 0);
+ jni_abort_catcher.Check(
+ "attempt to release char primitive array elements with an object of type boolean[]");
+ env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array),
+ reinterpret_cast<jint*>(elements), 0);
+ jni_abort_catcher.Check(
+ "attempt to release int primitive array elements with an object of type boolean[]");
+ env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array),
+ reinterpret_cast<jlong*>(elements), 0);
+ jni_abort_catcher.Check(
+ "attempt to release long primitive array elements with an object of type boolean[]");
+ env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array),
+ reinterpret_cast<jfloat*>(elements), 0);
+ jni_abort_catcher.Check(
+ "attempt to release float primitive array elements with an object of type boolean[]");
+ env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array),
+ reinterpret_cast<jdouble*>(elements), 0);
+ jni_abort_catcher.Check(
+ "attempt to release double primitive array elements with an object of type boolean[]");
+ jbyteArray array2 = env_->NewByteArray(10);
+ env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), elements, 0);
+ jni_abort_catcher.Check(
+ "attempt to release boolean primitive array elements with an object of type byte[]");
+ jobject object = env_->NewStringUTF("Test String");
+ env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), elements, 0);
+ jni_abort_catcher.Check(
+ "attempt to release boolean primitive array elements with an object of type java.lang.String");
+}
+TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) {
+ CheckJniAbortCatcher jni_abort_catcher;
+ jobject object = env_->NewStringUTF("Test String");
+ jboolean is_copy;
+ void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy);
+ jni_abort_catcher.Check("expected primitive array, given java.lang.String");
+ env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0);
+ jni_abort_catcher.Check("expected primitive array, given java.lang.String");
+}
+
+TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) {
+ CheckJniAbortCatcher jni_abort_catcher;
+ constexpr size_t kLength = 10;
+ jbooleanArray array = env_->NewBooleanArray(kLength);
+ ASSERT_TRUE(array != nullptr);
+ jboolean elements[kLength];
+ env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
+ reinterpret_cast<jbyte*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of byte primitive array elements with an object of type boolean[]");
+ env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
+ reinterpret_cast<jshort*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of short primitive array elements with an object of type boolean[]");
+ env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
+ reinterpret_cast<jchar*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of char primitive array elements with an object of type boolean[]");
+ env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
+ reinterpret_cast<jint*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of int primitive array elements with an object of type boolean[]");
+ env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
+ reinterpret_cast<jlong*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of long primitive array elements with an object of type boolean[]");
+ env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
+ reinterpret_cast<jfloat*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of float primitive array elements with an object of type boolean[]");
+ env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
+ reinterpret_cast<jdouble*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of double primitive array elements with an object of type boolean[]");
+ jbyteArray array2 = env_->NewByteArray(10);
+ env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
+ reinterpret_cast<jboolean*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of boolean primitive array elements with an object of type byte[]");
+ jobject object = env_->NewStringUTF("Test String");
+ env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
+ reinterpret_cast<jboolean*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to get region of boolean primitive array elements with an object of type java.lang.String");
+}
+
+TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) {
+ CheckJniAbortCatcher jni_abort_catcher;
+ constexpr size_t kLength = 10;
+ jbooleanArray array = env_->NewBooleanArray(kLength);
+ ASSERT_TRUE(array != nullptr);
+ jboolean elements[kLength];
+ env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
+ reinterpret_cast<jbyte*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of byte primitive array elements with an object of type boolean[]");
+ env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
+ reinterpret_cast<jshort*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of short primitive array elements with an object of type boolean[]");
+ env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
+ reinterpret_cast<jchar*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of char primitive array elements with an object of type boolean[]");
+ env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
+ reinterpret_cast<jint*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of int primitive array elements with an object of type boolean[]");
+ env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
+ reinterpret_cast<jlong*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of long primitive array elements with an object of type boolean[]");
+ env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
+ reinterpret_cast<jfloat*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of float primitive array elements with an object of type boolean[]");
+ env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
+ reinterpret_cast<jdouble*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of double primitive array elements with an object of type boolean[]");
+ jbyteArray array2 = env_->NewByteArray(10);
+ env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
+ reinterpret_cast<jboolean*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of boolean primitive array elements with an object of type byte[]");
+ jobject object = env_->NewStringUTF("Test String");
+ env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
+ reinterpret_cast<jboolean*>(elements));
+ jni_abort_catcher.Check(
+ "attempt to set region of boolean primitive array elements with an object of type java.lang.String");
+}
+
TEST_F(JniInternalTest, NewObjectArray) {
jclass element_class = env_->FindClass("java/lang/String");
- ASSERT_TRUE(element_class != nullptr);
+ ASSERT_NE(element_class, nullptr);
jclass array_class = env_->FindClass("[Ljava/lang/String;");
- ASSERT_TRUE(array_class != nullptr);
+ ASSERT_NE(array_class, nullptr);
jobjectArray a = env_->NewObjectArray(0, element_class, nullptr);
- EXPECT_TRUE(a != nullptr);
+ EXPECT_NE(a, nullptr);
EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
EXPECT_EQ(0, env_->GetArrayLength(a));
a = env_->NewObjectArray(1, element_class, nullptr);
- EXPECT_TRUE(a != nullptr);
+ EXPECT_NE(a, nullptr);
EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
EXPECT_EQ(1, env_->GetArrayLength(a));
EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr));
-}
-TEST_F(JniInternalTest, NewObjectArrayWithNegativeLength) {
- jclass element_class = env_->FindClass("java/lang/String");
- ASSERT_TRUE(element_class != nullptr);
- jclass array_class = env_->FindClass("[Ljava/lang/String;");
- ASSERT_TRUE(array_class != nullptr);
+ // Negative array length checks.
CheckJniAbortCatcher jni_abort_catcher;
-
env_->NewObjectArray(-1, element_class, nullptr);
jni_abort_catcher.Check("negative array length: -1");
@@ -521,6 +819,8 @@
CheckJniAbortCatcher jni_abort_catcher;
for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
+ env_->NewObjectArray(0, nullptr, nullptr);
+ jni_abort_catcher.Check("element_jclass == null");
jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
env_->NewObjectArray(1, primitive_class, nullptr);
std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
@@ -530,13 +830,13 @@
TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) {
jclass element_class = env_->FindClass("java/lang/String");
- ASSERT_TRUE(element_class != nullptr);
+ ASSERT_NE(element_class, nullptr);
jclass array_class = env_->FindClass("[Ljava/lang/String;");
- ASSERT_TRUE(array_class != nullptr);
+ ASSERT_NE(array_class, nullptr);
jstring s = env_->NewStringUTF("poop");
jobjectArray a = env_->NewObjectArray(2, element_class, s);
- EXPECT_TRUE(a != nullptr);
+ EXPECT_NE(a, nullptr);
EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
EXPECT_EQ(2, env_->GetArrayLength(a));
EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
@@ -555,9 +855,9 @@
TEST_F(JniInternalTest, GetObjectClass) {
jclass string_class = env_->FindClass("java/lang/String");
- ASSERT_TRUE(string_class != NULL);
+ ASSERT_NE(string_class, nullptr);
jclass class_class = env_->FindClass("java/lang/Class");
- ASSERT_TRUE(class_class != NULL);
+ ASSERT_NE(class_class, nullptr);
jstring s = env_->NewStringUTF("poop");
jclass c = env_->GetObjectClass(s);
@@ -565,33 +865,50 @@
jclass c2 = env_->GetObjectClass(c);
ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
+
+ // Null as object should fail.
+ CheckJniAbortCatcher jni_abort_catcher;
+ EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr);
+ jni_abort_catcher.Check("java_object == null");
}
TEST_F(JniInternalTest, GetSuperclass) {
jclass object_class = env_->FindClass("java/lang/Object");
- ASSERT_TRUE(object_class != NULL);
+ ASSERT_NE(object_class, nullptr);
jclass string_class = env_->FindClass("java/lang/String");
- ASSERT_TRUE(string_class != NULL);
+ ASSERT_NE(string_class, nullptr);
jclass runnable_interface = env_->FindClass("java/lang/Runnable");
- ASSERT_TRUE(runnable_interface != NULL);
+ ASSERT_NE(runnable_interface, nullptr);
ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
- ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL);
+ ASSERT_EQ(env_->GetSuperclass(object_class), nullptr);
ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
+
+ // Null as class should fail.
+ CheckJniAbortCatcher jni_abort_catcher;
+ EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
+ jni_abort_catcher.Check("java_class == null");
}
TEST_F(JniInternalTest, IsAssignableFrom) {
jclass object_class = env_->FindClass("java/lang/Object");
- ASSERT_TRUE(object_class != NULL);
+ ASSERT_NE(object_class, nullptr);
jclass string_class = env_->FindClass("java/lang/String");
- ASSERT_TRUE(string_class != NULL);
+ ASSERT_NE(string_class, nullptr);
ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class));
ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class));
+
+ // Null as either class should fail.
+ CheckJniAbortCatcher jni_abort_catcher;
+ EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
+ jni_abort_catcher.Check("java_class1 == null");
+ EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
+ jni_abort_catcher.Check("java_class2 == null");
}
TEST_F(JniInternalTest, GetObjectRefType) {
jclass local = env_->FindClass("java/lang/Object");
- ASSERT_TRUE(local != NULL);
+ ASSERT_TRUE(local != nullptr);
EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
jobject global = env_->NewGlobalRef(local);
@@ -604,33 +921,38 @@
EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
// TODO: invoke a native method and test that its arguments are considered local references.
+
+ // Null as object should fail.
+ CheckJniAbortCatcher jni_abort_catcher;
+ EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr));
+ jni_abort_catcher.Check("java_object == null");
}
TEST_F(JniInternalTest, StaleWeakGlobal) {
jclass java_lang_Class = env_->FindClass("java/lang/Class");
- ASSERT_TRUE(java_lang_Class != NULL);
- jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, NULL);
- ASSERT_TRUE(local_ref != NULL);
+ ASSERT_NE(java_lang_Class, nullptr);
+ jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr);
+ ASSERT_NE(local_ref, nullptr);
jweak weak_global = env_->NewWeakGlobalRef(local_ref);
- ASSERT_TRUE(weak_global != NULL);
+ ASSERT_NE(weak_global, nullptr);
env_->DeleteLocalRef(local_ref);
Runtime::Current()->GetHeap()->CollectGarbage(false); // GC should clear the weak global.
jobject new_global_ref = env_->NewGlobalRef(weak_global);
- EXPECT_TRUE(new_global_ref == NULL);
+ EXPECT_EQ(new_global_ref, nullptr);
jobject new_local_ref = env_->NewLocalRef(weak_global);
- EXPECT_TRUE(new_local_ref == NULL);
+ EXPECT_EQ(new_local_ref, nullptr);
}
TEST_F(JniInternalTest, NewStringUTF) {
- EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
+ EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr);
jstring s;
s = env_->NewStringUTF("");
- EXPECT_TRUE(s != NULL);
+ EXPECT_NE(s, nullptr);
EXPECT_EQ(0, env_->GetStringLength(s));
EXPECT_EQ(0, env_->GetStringUTFLength(s));
s = env_->NewStringUTF("hello");
- EXPECT_TRUE(s != NULL);
+ EXPECT_NE(s, nullptr);
EXPECT_EQ(5, env_->GetStringLength(s));
EXPECT_EQ(5, env_->GetStringUTFLength(s));
@@ -641,11 +963,11 @@
jchar chars[] = { 'h', 'i' };
jstring s;
s = env_->NewString(chars, 0);
- EXPECT_TRUE(s != NULL);
+ EXPECT_NE(s, nullptr);
EXPECT_EQ(0, env_->GetStringLength(s));
EXPECT_EQ(0, env_->GetStringUTFLength(s));
s = env_->NewString(chars, 2);
- EXPECT_TRUE(s != NULL);
+ EXPECT_NE(s, nullptr);
EXPECT_EQ(2, env_->GetStringLength(s));
EXPECT_EQ(2, env_->GetStringUTFLength(s));
@@ -654,7 +976,7 @@
TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
jstring s = env_->NewString(nullptr, 0);
- EXPECT_TRUE(s != nullptr);
+ EXPECT_NE(s, nullptr);
EXPECT_EQ(0, env_->GetStringLength(s));
}
@@ -678,16 +1000,16 @@
TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
jstring s = env_->NewStringUTF("hello");
- ASSERT_TRUE(s != NULL);
+ ASSERT_TRUE(s != nullptr);
- env_->GetStringRegion(s, -1, 0, NULL);
- EXPECT_EXCEPTION(sioobe_);
- env_->GetStringRegion(s, 0, -1, NULL);
- EXPECT_EXCEPTION(sioobe_);
- env_->GetStringRegion(s, 0, 10, NULL);
- EXPECT_EXCEPTION(sioobe_);
- env_->GetStringRegion(s, 10, 1, NULL);
- EXPECT_EXCEPTION(sioobe_);
+ env_->GetStringRegion(s, -1, 0, nullptr);
+ ExpectException(sioobe_);
+ env_->GetStringRegion(s, 0, -1, nullptr);
+ ExpectException(sioobe_);
+ env_->GetStringRegion(s, 0, 10, nullptr);
+ ExpectException(sioobe_);
+ env_->GetStringRegion(s, 10, 1, nullptr);
+ ExpectException(sioobe_);
jchar chars[4] = { 'x', 'x', 'x', 'x' };
env_->GetStringRegion(s, 1, 2, &chars[1]);
@@ -696,20 +1018,20 @@
EXPECT_EQ('l', chars[2]);
EXPECT_EQ('x', chars[3]);
- // It's okay for the buffer to be NULL as long as the length is 0.
- env_->GetStringRegion(s, 2, 0, NULL);
+ // It's okay for the buffer to be nullptr as long as the length is 0.
+ env_->GetStringRegion(s, 2, 0, nullptr);
// Even if the offset is invalid...
- env_->GetStringRegion(s, 123, 0, NULL);
- EXPECT_EXCEPTION(sioobe_);
+ env_->GetStringRegion(s, 123, 0, nullptr);
+ ExpectException(sioobe_);
- env_->GetStringUTFRegion(s, -1, 0, NULL);
- EXPECT_EXCEPTION(sioobe_);
- env_->GetStringUTFRegion(s, 0, -1, NULL);
- EXPECT_EXCEPTION(sioobe_);
- env_->GetStringUTFRegion(s, 0, 10, NULL);
- EXPECT_EXCEPTION(sioobe_);
- env_->GetStringUTFRegion(s, 10, 1, NULL);
- EXPECT_EXCEPTION(sioobe_);
+ env_->GetStringUTFRegion(s, -1, 0, nullptr);
+ ExpectException(sioobe_);
+ env_->GetStringUTFRegion(s, 0, -1, nullptr);
+ ExpectException(sioobe_);
+ env_->GetStringUTFRegion(s, 0, 10, nullptr);
+ ExpectException(sioobe_);
+ env_->GetStringUTFRegion(s, 10, 1, nullptr);
+ ExpectException(sioobe_);
char bytes[4] = { 'x', 'x', 'x', 'x' };
env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
@@ -718,25 +1040,25 @@
EXPECT_EQ('l', bytes[2]);
EXPECT_EQ('x', bytes[3]);
- // It's okay for the buffer to be NULL as long as the length is 0.
- env_->GetStringUTFRegion(s, 2, 0, NULL);
+ // It's okay for the buffer to be nullptr as long as the length is 0.
+ env_->GetStringUTFRegion(s, 2, 0, nullptr);
// Even if the offset is invalid...
- env_->GetStringUTFRegion(s, 123, 0, NULL);
- EXPECT_EXCEPTION(sioobe_);
+ env_->GetStringUTFRegion(s, 123, 0, nullptr);
+ ExpectException(sioobe_);
}
TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
- // Passing in a NULL jstring is ignored normally, but caught by -Xcheck:jni.
+ // Passing in a nullptr jstring is ignored normally, but caught by -Xcheck:jni.
{
CheckJniAbortCatcher check_jni_abort_catcher;
- EXPECT_TRUE(env_->GetStringUTFChars(NULL, NULL) == NULL);
+ EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
check_jni_abort_catcher.Check("GetStringUTFChars received null jstring");
}
jstring s = env_->NewStringUTF("hello");
- ASSERT_TRUE(s != NULL);
+ ASSERT_TRUE(s != nullptr);
- const char* utf = env_->GetStringUTFChars(s, NULL);
+ const char* utf = env_->GetStringUTFChars(s, nullptr);
EXPECT_STREQ("hello", utf);
env_->ReleaseStringUTFChars(s, utf);
@@ -749,10 +1071,10 @@
TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
jstring s = env_->NewStringUTF("hello");
- ASSERT_TRUE(s != NULL);
+ ASSERT_TRUE(s != nullptr);
jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
- const jchar* chars = env_->GetStringChars(s, NULL);
+ const jchar* chars = env_->GetStringChars(s, nullptr);
EXPECT_EQ(expected[0], chars[0]);
EXPECT_EQ(expected[1], chars[1]);
EXPECT_EQ(expected[2], chars[2]);
@@ -773,10 +1095,10 @@
TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
jstring s = env_->NewStringUTF("hello");
- ASSERT_TRUE(s != NULL);
+ ASSERT_TRUE(s != nullptr);
jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
- const jchar* chars = env_->GetStringCritical(s, NULL);
+ const jchar* chars = env_->GetStringCritical(s, nullptr);
EXPECT_EQ(expected[0], chars[0]);
EXPECT_EQ(expected[1], chars[1]);
EXPECT_EQ(expected[2], chars[2]);
@@ -798,45 +1120,72 @@
TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
jclass java_lang_Class = env_->FindClass("java/lang/Class");
- ASSERT_TRUE(java_lang_Class != NULL);
+ ASSERT_TRUE(java_lang_Class != nullptr);
- jobjectArray array = env_->NewObjectArray(1, java_lang_Class, NULL);
- EXPECT_TRUE(array != NULL);
- EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL);
+ jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr);
+ EXPECT_NE(array, nullptr);
+ EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr);
env_->SetObjectArrayElement(array, 0, java_lang_Class);
EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
// ArrayIndexOutOfBounds for negative index.
env_->SetObjectArrayElement(array, -1, java_lang_Class);
- EXPECT_EXCEPTION(aioobe_);
+ ExpectException(aioobe_);
// ArrayIndexOutOfBounds for too-large index.
env_->SetObjectArrayElement(array, 1, java_lang_Class);
- EXPECT_EXCEPTION(aioobe_);
+ ExpectException(aioobe_);
// ArrayStoreException thrown for bad types.
env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
- EXPECT_EXCEPTION(ase_);
+ ExpectException(ase_);
+
+ // Null as array should fail.
+ CheckJniAbortCatcher jni_abort_catcher;
+ EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
+ jni_abort_catcher.Check("java_array == null");
+ env_->SetObjectArrayElement(nullptr, 0, nullptr);
+ jni_abort_catcher.Check("java_array == null");
}
#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
do { \
jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
- EXPECT_TRUE(fid != NULL); \
+ EXPECT_NE(fid, nullptr); \
env_->SetStatic ## type ## Field(c, fid, value1); \
- EXPECT_TRUE(value1 == env_->GetStatic ## type ## Field(c, fid)); \
+ EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \
env_->SetStatic ## type ## Field(c, fid, value2); \
- EXPECT_TRUE(value2 == env_->GetStatic ## type ## Field(c, fid)); \
+ EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \
+ \
+ CheckJniAbortCatcher jni_abort_catcher; \
+ env_->GetStatic ## type ## Field(nullptr, fid); \
+ jni_abort_catcher.Check("received null jclass"); \
+ env_->SetStatic ## type ## Field(nullptr, fid, value1); \
+ jni_abort_catcher.Check("received null jclass"); \
+ env_->GetStatic ## type ## Field(c, nullptr); \
+ jni_abort_catcher.Check("fid == null"); \
+ env_->SetStatic ## type ## Field(c, nullptr, value1); \
+ jni_abort_catcher.Check("fid == null"); \
} while (false)
#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
do { \
jfieldID fid = env_->GetFieldID(c, field_name, sig); \
- EXPECT_TRUE(fid != NULL); \
+ EXPECT_NE(fid, nullptr); \
env_->Set ## type ## Field(instance, fid, value1); \
- EXPECT_TRUE(value1 == env_->Get ## type ## Field(instance, fid)); \
+ EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \
env_->Set ## type ## Field(instance, fid, value2); \
- EXPECT_TRUE(value2 == env_->Get ## type ## Field(instance, fid)); \
+ EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \
+ \
+ CheckJniAbortCatcher jni_abort_catcher; \
+ env_->Get ## type ## Field(nullptr, fid); \
+ jni_abort_catcher.Check("obj == null"); \
+ env_->Set ## type ## Field(nullptr, fid, value1); \
+ jni_abort_catcher.Check("obj == null"); \
+ env_->Get ## type ## Field(instance, nullptr); \
+ jni_abort_catcher.Check("fid == null"); \
+ env_->Set ## type ## Field(instance, nullptr, value1); \
+ jni_abort_catcher.Check("fid == null"); \
} while (false)
@@ -845,14 +1194,14 @@
Thread::Current()->TransitionFromSuspendedToRunnable();
LoadDex("AllFields");
bool started = runtime_->Start();
- CHECK(started);
+ ASSERT_TRUE(started);
jclass c = env_->FindClass("AllFields");
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
jobject o = env_->AllocObject(c);
- ASSERT_TRUE(o != NULL);
+ ASSERT_NE(o, nullptr);
- EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false);
+ EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE);
EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
@@ -861,7 +1210,7 @@
EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
- EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false);
+ EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE);
EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
@@ -878,19 +1227,19 @@
runtime_->Start();
jclass c = env_->FindClass("AllFields");
- ASSERT_TRUE(c != NULL);
+ ASSERT_NE(c, nullptr);
jobject o = env_->AllocObject(c);
- ASSERT_TRUE(o != NULL);
+ ASSERT_NE(o, nullptr);
jstring s1 = env_->NewStringUTF("hello");
- ASSERT_TRUE(s1 != NULL);
+ ASSERT_NE(s1, nullptr);
jstring s2 = env_->NewStringUTF("world");
- ASSERT_TRUE(s2 != NULL);
+ ASSERT_NE(s2, nullptr);
jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
- ASSERT_TRUE(s_fid != NULL);
+ ASSERT_NE(s_fid, nullptr);
jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
- ASSERT_TRUE(i_fid != NULL);
+ ASSERT_NE(i_fid, nullptr);
env_->SetStaticObjectField(c, s_fid, s1);
ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
@@ -903,27 +1252,27 @@
ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
}
-TEST_F(JniInternalTest, NewLocalRef_NULL) {
- EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
+TEST_F(JniInternalTest, NewLocalRef_nullptr) {
+ EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr);
}
TEST_F(JniInternalTest, NewLocalRef) {
jstring s = env_->NewStringUTF("");
- ASSERT_TRUE(s != NULL);
+ ASSERT_NE(s, nullptr);
jobject o = env_->NewLocalRef(s);
- EXPECT_TRUE(o != NULL);
- EXPECT_TRUE(o != s);
+ EXPECT_NE(o, nullptr);
+ EXPECT_NE(o, s);
EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
}
-TEST_F(JniInternalTest, DeleteLocalRef_NULL) {
- env_->DeleteLocalRef(NULL);
+TEST_F(JniInternalTest, DeleteLocalRef_nullptr) {
+ env_->DeleteLocalRef(nullptr);
}
TEST_F(JniInternalTest, DeleteLocalRef) {
jstring s = env_->NewStringUTF("");
- ASSERT_TRUE(s != NULL);
+ ASSERT_NE(s, nullptr);
env_->DeleteLocalRef(s);
// Currently, deleting an already-deleted reference is just a CheckJNI warning.
@@ -937,9 +1286,9 @@
}
s = env_->NewStringUTF("");
- ASSERT_TRUE(s != NULL);
+ ASSERT_NE(s, nullptr);
jobject o = env_->NewLocalRef(s);
- ASSERT_TRUE(o != NULL);
+ ASSERT_NE(o, nullptr);
env_->DeleteLocalRef(s);
env_->DeleteLocalRef(o);
@@ -951,7 +1300,7 @@
// Android historically treated it, and it's how the RI treats it. It's also the more useful
// interpretation!
ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
- env_->PopLocalFrame(NULL);
+ env_->PopLocalFrame(nullptr);
// Negative capacities are not allowed.
ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
@@ -962,7 +1311,7 @@
TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
jobject original = env_->NewStringUTF("");
- ASSERT_TRUE(original != NULL);
+ ASSERT_NE(original, nullptr);
jobject outer;
jobject inner1, inner2;
@@ -988,7 +1337,7 @@
// gets a new local reference...
EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
- env_->PopLocalFrame(NULL);
+ env_->PopLocalFrame(nullptr);
}
EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
@@ -996,30 +1345,30 @@
EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
}
-TEST_F(JniInternalTest, NewGlobalRef_NULL) {
- EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL);
+TEST_F(JniInternalTest, NewGlobalRef_nullptr) {
+ EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr);
}
TEST_F(JniInternalTest, NewGlobalRef) {
jstring s = env_->NewStringUTF("");
- ASSERT_TRUE(s != NULL);
+ ASSERT_NE(s, nullptr);
jobject o = env_->NewGlobalRef(s);
- EXPECT_TRUE(o != NULL);
- EXPECT_TRUE(o != s);
+ EXPECT_NE(o, nullptr);
+ EXPECT_NE(o, s);
- // TODO: check that o is a global reference.
+ EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType);
}
-TEST_F(JniInternalTest, DeleteGlobalRef_NULL) {
- env_->DeleteGlobalRef(NULL);
+TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) {
+ env_->DeleteGlobalRef(nullptr);
}
TEST_F(JniInternalTest, DeleteGlobalRef) {
jstring s = env_->NewStringUTF("");
- ASSERT_TRUE(s != NULL);
+ ASSERT_NE(s, nullptr);
jobject o = env_->NewGlobalRef(s);
- ASSERT_TRUE(o != NULL);
+ ASSERT_NE(o, nullptr);
env_->DeleteGlobalRef(o);
// Currently, deleting an already-deleted reference is just a CheckJNI warning.
@@ -1033,38 +1382,38 @@
}
jobject o1 = env_->NewGlobalRef(s);
- ASSERT_TRUE(o1 != NULL);
+ ASSERT_NE(o1, nullptr);
jobject o2 = env_->NewGlobalRef(s);
- ASSERT_TRUE(o2 != NULL);
+ ASSERT_NE(o2, nullptr);
env_->DeleteGlobalRef(o1);
env_->DeleteGlobalRef(o2);
}
-TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) {
- EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL);
+TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) {
+ EXPECT_EQ(env_->NewWeakGlobalRef(nullptr), nullptr);
}
TEST_F(JniInternalTest, NewWeakGlobalRef) {
jstring s = env_->NewStringUTF("");
- ASSERT_TRUE(s != NULL);
+ ASSERT_NE(s, nullptr);
jobject o = env_->NewWeakGlobalRef(s);
- EXPECT_TRUE(o != NULL);
- EXPECT_TRUE(o != s);
+ EXPECT_NE(o, nullptr);
+ EXPECT_NE(o, s);
- // TODO: check that o is a weak global reference.
+ EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType);
}
-TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) {
- env_->DeleteWeakGlobalRef(NULL);
+TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) {
+ env_->DeleteWeakGlobalRef(nullptr);
}
TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
jstring s = env_->NewStringUTF("");
- ASSERT_TRUE(s != NULL);
+ ASSERT_NE(s, nullptr);
jobject o = env_->NewWeakGlobalRef(s);
- ASSERT_TRUE(o != NULL);
+ ASSERT_NE(o, nullptr);
env_->DeleteWeakGlobalRef(o);
// Currently, deleting an already-deleted reference is just a CheckJNI warning.
@@ -1078,21 +1427,21 @@
}
jobject o1 = env_->NewWeakGlobalRef(s);
- ASSERT_TRUE(o1 != NULL);
+ ASSERT_NE(o1, nullptr);
jobject o2 = env_->NewWeakGlobalRef(s);
- ASSERT_TRUE(o2 != NULL);
+ ASSERT_NE(o2, nullptr);
env_->DeleteWeakGlobalRef(o1);
env_->DeleteWeakGlobalRef(o2);
}
TEST_F(JniInternalTest, Throw) {
- EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
+ EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
jclass exception_class = env_->FindClass("java/lang/RuntimeException");
- ASSERT_TRUE(exception_class != NULL);
+ ASSERT_TRUE(exception_class != nullptr);
jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
- ASSERT_TRUE(exception != NULL);
+ ASSERT_TRUE(exception != nullptr);
EXPECT_EQ(JNI_OK, env_->Throw(exception));
EXPECT_TRUE(env_->ExceptionCheck());
@@ -1102,10 +1451,10 @@
}
TEST_F(JniInternalTest, ThrowNew) {
- EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
+ EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
jclass exception_class = env_->FindClass("java/lang/RuntimeException");
- ASSERT_TRUE(exception_class != NULL);
+ ASSERT_TRUE(exception_class != nullptr);
jthrowable thrown_exception;
@@ -1115,7 +1464,7 @@
env_->ExceptionClear();
EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
- EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL));
+ EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr));
EXPECT_TRUE(env_->ExceptionCheck());
thrown_exception = env_->ExceptionOccurred();
env_->ExceptionClear();
@@ -1141,26 +1490,26 @@
ASSERT_TRUE(started);
jclass buffer_class = env_->FindClass("java/nio/Buffer");
- ASSERT_TRUE(buffer_class != NULL);
+ ASSERT_NE(buffer_class, nullptr);
char bytes[1024];
jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
- ASSERT_TRUE(buffer != NULL);
+ ASSERT_NE(buffer, nullptr);
ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
- ASSERT_TRUE(env_->GetDirectBufferAddress(buffer) == bytes);
- ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes));
+ ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes);
+ ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes)));
}
TEST_F(JniInternalTest, MonitorEnterExit) {
- // Create an object to torture
+ // Create an object to torture.
jclass object_class = env_->FindClass("java/lang/Object");
- ASSERT_TRUE(object_class != NULL);
+ ASSERT_NE(object_class, nullptr);
jobject object = env_->AllocObject(object_class);
- ASSERT_TRUE(object != NULL);
+ ASSERT_NE(object, nullptr);
// Expected class of exceptions
jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
- ASSERT_TRUE(imse_class != NULL);
+ ASSERT_NE(imse_class, nullptr);
jthrowable thrown_exception;
@@ -1197,13 +1546,13 @@
env_->ExceptionClear();
EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
- // It's an error to call MonitorEnter or MonitorExit on NULL.
+ // It's an error to call MonitorEnter or MonitorExit on nullptr.
{
CheckJniAbortCatcher check_jni_abort_catcher;
- env_->MonitorEnter(NULL);
+ env_->MonitorEnter(nullptr);
check_jni_abort_catcher.Check("in call to MonitorEnter");
- env_->MonitorExit(NULL);
+ env_->MonitorExit(nullptr);
check_jni_abort_catcher.Check("in call to MonitorExit");
}
}
@@ -1215,7 +1564,7 @@
jint err = vm_->DetachCurrentThread();
EXPECT_EQ(JNI_ERR, err);
- vm_->AttachCurrentThread(&env_, NULL); // need attached thread for CommonRuntimeTest::TearDown
+ vm_->AttachCurrentThread(&env_, nullptr); // need attached thread for CommonRuntimeTest::TearDown
}
} // namespace art
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 238506e..1b8106e 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -155,14 +155,19 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void SetArrayClass(Class* array_class) {
- CHECK(array_class_ == NULL);
- CHECK(array_class != NULL);
+ CHECK(array_class_ == nullptr);
+ CHECK(array_class != nullptr);
array_class_ = array_class;
}
+ static Class* GetArrayClass() {
+ DCHECK(array_class_ != nullptr);
+ return array_class_;
+ }
+
static void ResetArrayClass() {
- CHECK(array_class_ != NULL);
- array_class_ = NULL;
+ CHECK(array_class_ != nullptr);
+ array_class_ = nullptr;
}
static void VisitRoots(RootCallback* callback, void* arg)
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 822e0fb..64edba8 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -642,21 +642,22 @@
} else {
ThreadList* thread_list = Runtime::Current()->GetThreadList();
// Suspend the owner, inflate. First change to blocked and give up mutator_lock_.
- ScopedThreadStateChange tsc(self, kBlocked);
self->SetMonitorEnterObject(obj.Get());
- if (lock_word == obj->GetLockWord(true)) { // If lock word hasn't changed.
- bool timed_out;
- Thread* owner = thread_list->SuspendThreadByThreadId(owner_thread_id, false, &timed_out);
- if (owner != nullptr) {
- // We succeeded in suspending the thread, check the lock's status didn't change.
- lock_word = obj->GetLockWord(true);
- if (lock_word.GetState() == LockWord::kThinLocked &&
- lock_word.ThinLockOwner() == owner_thread_id) {
- // Go ahead and inflate the lock.
- Inflate(self, owner, obj.Get(), hash_code);
- }
- thread_list->Resume(owner, false);
+ bool timed_out;
+ Thread* owner;
+ {
+ ScopedThreadStateChange tsc(self, kBlocked);
+ owner = thread_list->SuspendThreadByThreadId(owner_thread_id, false, &timed_out);
+ }
+ if (owner != nullptr) {
+ // We succeeded in suspending the thread, check the lock's status didn't change.
+ lock_word = obj->GetLockWord(true);
+ if (lock_word.GetState() == LockWord::kThinLocked &&
+ lock_word.ThinLockOwner() == owner_thread_id) {
+ // Go ahead and inflate the lock.
+ Inflate(self, owner, obj.Get(), hash_code);
}
+ thread_list->Resume(owner, false);
}
self->SetMonitorEnterObject(nullptr);
}
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 50a8e47..8d183da 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -66,10 +66,6 @@
ThrowNullPointerException(NULL, "element class == null");
return nullptr;
}
- if (UNLIKELY(element_class->IsPrimitiveVoid())) {
- ThrowIllegalArgumentException(NULL, "Can't allocate an array of void");
- return nullptr;
- }
Runtime* runtime = Runtime::Current();
mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == nullptr)) {
@@ -93,10 +89,6 @@
ThrowNullPointerException(NULL, "element class == null");
return nullptr;
}
- if (UNLIKELY(element_class->IsPrimitiveVoid())) {
- ThrowIllegalArgumentException(NULL, "Can't allocate an array of void");
- return nullptr;
- }
Runtime* runtime = Runtime::Current();
mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == nullptr)) {
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 623b0c6..55b6a27 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -689,9 +689,7 @@
if (compiler_callbacks_ == nullptr && image_.empty()) {
image_ += GetAndroidRoot();
- image_ += "/framework/boot-";
- image_ += GetInstructionSetString(image_isa_);
- image_ += ".art";
+ image_ += "/framework/boot.art";
}
if (heap_growth_limit_ == 0) {
heap_growth_limit_ = heap_maximum_size_;
diff --git a/test/Android.mk b/test/Android.mk
index aacd7b4..6e37af3 100644
--- a/test/Android.mk
+++ b/test/Android.mk
@@ -78,7 +78,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common.mk
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
include $(BUILD_JAVA_LIBRARY)
-
+
ART_TEST_TARGET_DEX_FILES += $$(LOCAL_INSTALLED_MODULE)
ART_TEST_TARGET_DEX_FILES$(ART_PHONY_TEST_TARGET_SUFFIX) += $$(LOCAL_INSTALLED_MODULE)
@@ -88,7 +88,7 @@
# TODO: make this a simple copy
$(4)/$(1)-$(2).jar: $(3)/$(1)-$(2).jar $(4)
cp $$< $(4)/
- endif
+ endif
endif
ifeq ($(ART_BUILD_HOST),true)
@@ -108,6 +108,9 @@
$(foreach dir,$(TEST_DEX_DIRECTORIES), $(eval $(call build-art-test-dex,art-test-dex,$(dir),$(ART_NATIVETEST_OUT),$(2ND_ART_NATIVETEST_OUT))))
$(foreach dir,$(TEST_OAT_DIRECTORIES), $(eval $(call build-art-test-dex,oat-test-dex,$(dir),$(ART_TEST_OUT),$(2ND_ART_TEST_OUT))))
+# Used outside the art project to get a list of the current tests
+ART_TEST_DEX_MAKE_TARGETS := $(addprefix art-test-dex-, $(TEST_DEX_DIRECTORIES))
+
# Rules to explicitly create 2nd-arch test directories, as we use a "cp" for them
# instead of BUILD_JAVA_LIBRARY
ifneq ($(2ND_ART_NATIVETEST_OUT),)
@@ -151,7 +154,7 @@
$(call declare-test-art-oat-targets-impl,$(1),)
$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).odex: $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar $(HOST_CORE_IMG_OUT) | $(DEX2OATD)
- $(DEX2OATD) $(DEX2OAT_FLAGS) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(HOST_CORE_IMG_OUT) --dex-file=$(PWD)/$$< --oat-file=$(PWD)/$$@ --instruction-set=$(ART_HOST_ARCH) --host --android-root=$(HOST_OUT)
+ $(DEX2OATD) $(DEX2OAT_FLAGS) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(HOST_CORE_IMG_OUT) --dex-file=$$(realpath $$<) --oat-file=$$(realpath $(HOST_OUT_JAVA_LIBRARIES))/oat-test-dex-$(1).odex --instruction-set=$(ART_HOST_ARCH) --host --android-root=$(HOST_OUT)
.PHONY: test-art-host-oat-default-$(1)
test-art-host-oat-default-$(1): $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).odex test-art-host-dependencies
@@ -159,7 +162,7 @@
ANDROID_DATA=/tmp/android-data/test-art-host-oat-default-$(1) \
ANDROID_ROOT=$(HOST_OUT) \
LD_LIBRARY_PATH=$(HOST_OUT_SHARED_LIBRARIES) \
- $(HOST_OUT_EXECUTABLES)/dalvikvm $(DALVIKVM_FLAGS) -XXlib:libartd.so -Ximage:$(shell pwd)/$(HOST_CORE_IMG_OUT) -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
+ $(HOST_OUT_EXECUTABLES)/dalvikvm $(DALVIKVM_FLAGS) -XXlib:libartd.so -Ximage:$$(realpath $(HOST_CORE_IMG_OUT)) -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
&& echo test-art-host-oat-default-$(1) PASSED || (echo test-art-host-oat-default-$(1) FAILED && exit 1)
$(hide) rm -r /tmp/android-data/test-art-host-oat-default-$(1)
@@ -169,7 +172,7 @@
ANDROID_DATA=/tmp/android-data/test-art-host-oat-interpreter-$(1) \
ANDROID_ROOT=$(HOST_OUT) \
LD_LIBRARY_PATH=$(HOST_OUT_SHARED_LIBRARIES) \
- $(HOST_OUT_EXECUTABLES)/dalvikvm -XXlib:libartd.so -Ximage:$(shell pwd)/$(HOST_CORE_IMG_OUT) -Xint -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
+ $(HOST_OUT_EXECUTABLES)/dalvikvm -XXlib:libartd.so -Ximage:$$(realpath $(HOST_CORE_IMG_OUT)) -Xint -classpath $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar -Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) $(1) $(2) \
&& echo test-art-host-oat-interpreter-$(1) PASSED || (echo test-art-host-oat-interpreter-$(1) FAILED && exit 1)
$(hide) rm -r /tmp/android-data/test-art-host-oat-interpreter-$(1)