Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit f9a22c9

Browse files
committed
Switch to borrowed strings in constant pool
1 parent 8f35ae0 commit f9a22c9

File tree

7 files changed

+108
-82
lines changed

7 files changed

+108
-82
lines changed

enjarify-rs/src/dex.rs

+66-41
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414
use std::collections::HashSet;
1515
// use std::fmt;
16+
use std::ops::Deref;
1617
use std::str;
1718

1819
use strings::*;
@@ -21,7 +22,7 @@ use dalvik::{DalvikInstruction, parse_bytecode};
2122

2223
const NO_INDEX: u32 = 0xFFFFFFFF;
2324

24-
fn type_list<'a>(dex: &'a DexFile<'a>, off: u32, parse_cls_desc: bool) -> Vec<&'a bstr> {
25+
fn type_list<'a>(dex: &DexFileNoProtos<'a>, off: u32, parse_cls_desc: bool) -> Vec<&'a bstr> {
2526
if off == 0 { return Vec::new(); }
2627

2728
let mut st = dex.stream(off);
@@ -89,7 +90,7 @@ pub struct FieldId<'a> {
8990
pub desc: &'a bstr,
9091
}
9192
impl<'a> FieldId<'a> {
92-
fn new(dex: &'a DexFile<'a>, field_idx: u32) -> FieldId<'a> {
93+
fn new(dex: &DexFile<'a>, field_idx: u32) -> FieldId<'a> {
9394
let mut st = dex.stream(dex.field_ids.off + field_idx*8);
9495
FieldId{
9596
cname: dex.cls_type(st.u16() as u32),
@@ -191,15 +192,30 @@ impl<'a> CodeItem<'a> {
191192
}
192193
}
193194

195+
fn parse_prototype<'a>(dex: &DexFileNoProtos<'a>, proto_idx: u32) -> (BString, Vec<&'a bstr>, &'a bstr) {
196+
let mut st = dex.stream(dex.proto_ids.off + proto_idx * 12);
197+
st.u32();
198+
let return_type = dex.raw_type(st.u32());
199+
let param_types = type_list(dex, st.u32(), false);
200+
201+
let mut desc = vec![b'('];
202+
for part in &param_types {
203+
desc.extend_from_slice(part);
204+
}
205+
desc.push(b')');
206+
desc.extend_from_slice(return_type);
207+
(desc, param_types, return_type)
208+
}
209+
194210
pub struct MethodId<'a> {
195211
pub cname: &'a bstr,
196212
pub name: &'a bstr,
197-
pub desc: BString,
213+
pub desc: &'a bstr,
198214
pub return_type: &'a bstr,
199215
pub method_idx: u32,
200216

217+
proto_idx: u32,
201218
cdesc: &'a bstr,
202-
param_types: Vec<&'a bstr>,
203219
}
204220
impl<'a> MethodId<'a> {
205221
fn new(dex: &'a DexFile<'a>, method_idx: u32) -> MethodId<'a> {
@@ -209,35 +225,24 @@ impl<'a> MethodId<'a> {
209225
let proto_idx = st.u16() as u32;
210226
let name = dex.string(st.u32());
211227

212-
st = dex.stream(dex.proto_ids.off + proto_idx * 12);
213-
st.u32();
214-
let return_type = dex.raw_type(st.u32());
215-
let param_types = type_list(dex, st.u32(), false);
216-
217-
let mut desc = vec![b'('];
218-
for part in &param_types {
219-
desc.extend_from_slice(part);
220-
}
221-
desc.push(b')');
222-
desc.extend_from_slice(return_type);
223-
224228
MethodId{
225229
cname: cname,
226230
name: name,
227-
desc: desc,
228-
return_type: return_type,
231+
desc: &dex.proto(proto_idx).0,
232+
return_type: dex.proto(proto_idx).2,
229233
method_idx: method_idx,
234+
proto_idx: proto_idx,
230235

231236
cdesc: dex.raw_type(cname_idx),
232-
param_types: param_types,
233237
}
234238
}
235239

236-
pub fn spaced_param_types(&self, isstatic: bool) -> Vec<Option<&'a bstr>> {
237-
let mut res = Vec::with_capacity(self.param_types.len() + 1);
240+
pub fn spaced_param_types(&self, dex: &DexFile<'a>, isstatic: bool) -> Vec<Option<&'a bstr>> {
241+
let param_types = &dex.proto(self.proto_idx).1;
242+
let mut res = Vec::with_capacity(param_types.len() + 1);
238243
if !isstatic { res.push(Some(self.cdesc)); }
239244

240-
for param in &self.param_types {
245+
for param in param_types {
241246
res.push(Some(param));
242247
if param[0] == b'J' || param[0] == b'D' { res.push(None); }
243248
}
@@ -350,19 +355,17 @@ impl SizeOff {
350355
}
351356
}
352357

353-
#[allow(dead_code)] //data is not used
354-
pub struct DexFile<'a> {
358+
pub struct DexFileNoProtos<'a> {
355359
raw: &'a bstr,
356360
string_ids: SizeOff,
357361
type_ids: SizeOff,
358362
proto_ids: SizeOff,
359363
field_ids: SizeOff,
360364
method_ids: SizeOff,
361365
class_defs: SizeOff,
362-
data: SizeOff,
363366
}
364-
impl<'a> DexFile<'a> {
365-
pub fn new(data: &bstr) -> DexFile {
367+
impl<'a> DexFileNoProtos<'a> {
368+
pub fn new(data: &bstr) -> DexFileNoProtos {
366369
let mut stream = Reader(data);
367370
stream.read(36);
368371
if stream.u32() != 0x70 {
@@ -375,24 +378,17 @@ impl<'a> DexFile<'a> {
375378
SizeOff::new(&mut stream);
376379
stream.u32();
377380

378-
DexFile {
381+
DexFileNoProtos {
379382
raw: data,
380383
string_ids: SizeOff::new(&mut stream),
381384
type_ids: SizeOff::new(&mut stream),
382385
proto_ids: SizeOff::new(&mut stream),
383386
field_ids: SizeOff::new(&mut stream),
384387
method_ids: SizeOff::new(&mut stream),
385388
class_defs: SizeOff::new(&mut stream),
386-
data: SizeOff::new(&mut stream),
389+
// data: SizeOff::new(&mut stream),
387390
}
388391
}
389-
pub fn parse_classes(&'a self) -> Vec<DexClass<'a>> {
390-
let mut classes = Vec::with_capacity(self.class_defs.size as usize);
391-
for i in 0..self.class_defs.size {
392-
classes.push(DexClass::new(&self, self.class_defs.off, i));
393-
}
394-
classes
395-
}
396392

397393
fn stream(&self, offset: u32) -> Reader<'a> {
398394
Reader(self.raw.split_at(offset as usize).1)
@@ -401,29 +397,58 @@ impl<'a> DexFile<'a> {
401397
self.stream(i).u32()
402398
}
403399

404-
pub fn string(&self, i: u32) -> &bstr {
400+
pub fn string(&self, i: u32) -> &'a bstr {
405401
let data_off = self.u32(self.string_ids.off + i*4);
406402
let mut stream = self.stream(data_off);
407403
stream.uleb128(); // Ignore decoded length
408404
stream.cstr()
409405
}
410406

411-
pub fn raw_type(&self, i: u32) -> &bstr {
407+
pub fn raw_type(&self, i: u32) -> &'a bstr {
412408
assert!(i < self.type_ids.size);
413409
self.string(self.u32(self.type_ids.off + i*4))
414410
}
415411

416-
pub fn cls_type(&self, i: u32) -> &bstr {
412+
pub fn cls_type(&self, i: u32) -> &'a bstr {
417413
let data = self.raw_type(i);
418414
if data[0] == b'L' {
419415
&data[1..data.len()-1]
420416
} else { data }
421417
}
422418

423-
fn cls_type_opt(&self, i: u32) -> Option<&bstr> {
419+
fn cls_type_opt(&self, i: u32) -> Option<&'a bstr> {
424420
if i == NO_INDEX { None } else { Some(self.cls_type(i)) }
425421
}
422+
}
423+
424+
pub struct DexFile<'a> {
425+
dex: DexFileNoProtos<'a>,
426+
protos: Vec<(BString, Vec<&'a bstr>, &'a bstr)>,
427+
}
428+
impl<'a> Deref for DexFile<'a> {
429+
type Target = DexFileNoProtos<'a>;
430+
fn deref(&self) -> &Self::Target { &self.dex }
431+
}
432+
impl<'a> DexFile<'a> {
433+
pub fn new(data: &bstr) -> DexFile {
434+
let dex = DexFileNoProtos::new(data);
435+
let n = dex.proto_ids.size;
436+
let mut protos = Vec::with_capacity(n as usize);
437+
for i in 0..n {
438+
protos.push(parse_prototype(&dex, i));
439+
}
440+
DexFile{dex: dex, protos: protos}
441+
}
442+
443+
pub fn parse_classes(&'a self) -> Vec<DexClass<'a>> {
444+
let mut classes = Vec::with_capacity(self.class_defs.size as usize);
445+
for i in 0..self.class_defs.size {
446+
classes.push(DexClass::new(&self, self.class_defs.off, i));
447+
}
448+
classes
449+
}
426450

427451
pub fn field_id(&self, i: u32) -> FieldId { FieldId::new(self, i) }
428452
pub fn method_id(&self, i: u32) -> MethodId { MethodId::new(self, i) }
429-
}
453+
fn proto(&self, i: u32) -> &(BString, Vec<&'a bstr>, &'a bstr) { &self.protos[i as usize] }
454+
}

enjarify-rs/src/jvm/constantpool.rs

+18-23
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,23 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
use std::borrow::Cow;
1514
use std::collections::HashMap;
16-
use std::ops::Deref;
1715

1816
use strings::*;
1917
use byteio::Writer;
2018
use dex::{FieldId, MethodId};
2119
use error;
2220

23-
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
24-
pub struct ArgsUtf<'a>(Cow<'a, bstr>);
25-
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
21+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
22+
pub struct ArgsUtf<'a>(&'a bstr);
23+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
2624
pub struct ArgsInd(u16);
27-
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
25+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
2826
pub struct ArgsInd2(u16, u16);
29-
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
27+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
3028
pub struct ArgsPrim(pub u64);
3129

32-
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
30+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
3331
pub enum Entry<'a> {
3432
Class(ArgsInd),
3533
Fieldref(ArgsInd2),
@@ -106,47 +104,44 @@ pub trait ConstantPool<'a> {
106104
Some(self.insert_directly(entry, true))
107105
}
108106

109-
fn _utf8(&mut self, s: Cow<'a, bstr>) -> u16 {
107+
fn utf8(&mut self, s: &'a bstr) -> u16 {
110108
if s.len() > 65535 {
111109
error::classfile_limit_exceeded();
112110
}
113111
self.get(Utf8(ArgsUtf(s)))
114112
}
115-
fn utf8(&mut self, s: &'a bstr) -> u16 { self._utf8(s.into()) }
116113

117-
fn _class(&mut self, s: Cow<'a, bstr>) -> u16 {
118-
let ind = self._utf8(s);
114+
fn class(&mut self, s: &'a bstr) -> u16 {
115+
let ind = self.utf8(s);
119116
self.get(Class(ArgsInd(ind)))
120117
}
121-
fn class(&mut self, s: &'a bstr) -> u16 { self._class(s.into()) }
122118

123-
fn _string(&mut self, s: Cow<'a, bstr>) -> u16 {
124-
let ind = self._utf8(s);
119+
fn string(&mut self, s: &'a bstr) -> u16 {
120+
let ind = self.utf8(s);
125121
self.get(JString(ArgsInd(ind)))
126122
}
127-
fn string(&mut self, s: &'a bstr) -> u16 { self._string(s.into()) }
128123

129-
fn _nat(&mut self, name: Cow<'a, bstr>, desc: Cow<'a, bstr>) -> u16 {
130-
let ind = self._utf8(name);
131-
let ind2 = self._utf8(desc);
124+
fn _nat(&mut self, name: &'a bstr, desc: &'a bstr) -> u16 {
125+
let ind = self.utf8(name);
126+
let ind2 = self.utf8(desc);
132127
self.get(NameAndType(ArgsInd2(ind, ind2)))
133128
}
134129

135130
fn field(&mut self, trip: &FieldId<'a>) -> u16 {
136131
let ind = self.class(trip.cname);
137-
let ind2 = self._nat(trip.name.into(), trip.desc.into());
132+
let ind2 = self._nat(trip.name, trip.desc);
138133
self.get(Fieldref(ArgsInd2(ind, ind2)))
139134
}
140135

141136
fn method(&mut self, trip: MethodId<'a>) -> u16 {
142137
let ind = self.class(trip.cname);
143-
let ind2 = self._nat(trip.name.into(), trip.desc.into());
138+
let ind2 = self._nat(trip.name, trip.desc);
144139
self.get(Methodref(ArgsInd2(ind, ind2)))
145140
}
146141

147142
fn imethod(&mut self, trip: MethodId<'a>) -> u16 {
148143
let ind = self.class(trip.cname);
149-
let ind2 = self._nat(trip.name.into(), trip.desc.into());
144+
let ind2 = self._nat(trip.name, trip.desc);
150145
self.get(InterfaceMethodref(ArgsInd2(ind, ind2)))
151146
}
152147

@@ -170,7 +165,7 @@ pub trait ConstantPool<'a> {
170165
&NameAndType(ref args) => { stream.u8(12); stream.u16(args.0); stream.u16(args.1); },
171166
&Utf8(ref args) => { stream.u8(1);
172167
stream.u16(args.0.len() as u16);
173-
stream.write(args.0.deref());
168+
stream.write(args.0);
174169
},
175170
}
176171
}

enjarify-rs/src/jvm/irbuilder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl <'b, 'a> IRBlock<'b, 'a> {
115115
} else {
116116
// note - will throw if actual type is boolean[] but there's not
117117
// much we can do in this case
118-
self.pool._class(at.to_desc().into())
118+
self.pool.class(at.to_desc())
119119
};
120120
self.u8u16(CHECKCAST, ind);
121121
}
@@ -447,7 +447,7 @@ pub fn write_instruction<'b, 'a>(pool: &'b mut (ConstantPool<'a> + 'a), method:
447447
let args = instr.args.as_ref().unwrap();
448448
let rtype = called_id.return_type;
449449

450-
for (reg, desc) in args.iter().zip(called_id.spaced_param_types(isstatic)) {
450+
for (reg, desc) in args.iter().zip(called_id.spaced_param_types(dex, isstatic)) {
451451
if let Some(desc) = desc { // skip long/double tops
452452
block.load_desc(*reg, desc);
453453
}

enjarify-rs/src/jvm/writeclass.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ fn write_methods<'a>(pool: &mut (ConstantPool<'a> + 'a), stream: &mut Writer, me
6464
for method in methods {
6565
stream.u16(method.access as u16 & flags::METHOD_FLAGS);
6666
stream.u16(pool.utf8(method.id.name));
67-
stream.u16(pool._utf8(method.id.desc.into()));
67+
stream.u16(pool.utf8(method.id.desc));
6868

6969
match code_attrs.get(&method.id.method_idx) {
7070
Some(data) => {

enjarify-rs/src/jvm/writeir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub fn write_bytecode<'b, 'a>(pool: &'b mut (ConstantPool<'a> + 'a), method: &de
149149
}
150150

151151
let isstatic = method.access as u16 & flags::ACC_STATIC != 0;
152-
let arg_descs = method.id.spaced_param_types(isstatic);
152+
let arg_descs = method.id.spaced_param_types(dex, isstatic);
153153
let regoff = code.nregs - arg_descs.len() as u16;
154154
let mut iargs = Vec::with_capacity(arg_descs.len());
155155
for (i, optdesc) in arg_descs.iter().enumerate() {

enjarify-rs/src/typeinference/array.rs

+19-13
Original file line numberDiff line numberDiff line change
@@ -83,23 +83,29 @@ impl T {
8383
}
8484
}
8585

86-
pub fn to_desc(self) -> BString {
87-
// todo: return static slice?
86+
pub fn to_desc(self) -> &'static bstr {
8887
if let T::Array(dim, base) = self {
89-
let mut res = vec![b'['; dim as usize];
90-
res.push(match base {
91-
Base::B => b'B',
92-
Base::C => b'C',
93-
Base::S => b'S',
94-
Base::I => b'I',
95-
Base::F => b'F',
96-
Base::J => b'J',
97-
Base::D => b'D',
98-
});
99-
res
88+
let offset = 255-dim as usize;
89+
match base {
90+
Base::B => &BDESC[offset..],
91+
Base::C => &CDESC[offset..],
92+
Base::S => &SDESC[offset..],
93+
Base::I => &IDESC[offset..],
94+
Base::F => &FDESC[offset..],
95+
Base::J => &JDESC[offset..],
96+
Base::D => &DDESC[offset..],
97+
}
10098
} else { unreachable!(); }
10199
}
102100
}
103101

102+
static BDESC: &'static bstr = b"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[B";
103+
static CDESC: &'static bstr = b"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[C";
104+
static SDESC: &'static bstr = b"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[S";
105+
static IDESC: &'static bstr = b"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[I";
106+
static FDESC: &'static bstr = b"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[F";
107+
static JDESC: &'static bstr = b"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[J";
108+
static DDESC: &'static bstr = b"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[D";
109+
104110
pub const INVALID: T = T::Invalid;
105111
pub const NULL: T = T::Null;

0 commit comments

Comments
 (0)