leptris 1.9.222.1-arm-linux → 1.9.222.3-arm-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/leptris/native/native.c +81 -44
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/element.rb +25 -1
- data/lib/leptris/xml/native.so +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7532c10f6daec3e59677e99c9f0159e0aa724c2755a6e86f66093c86f5895ccb
|
|
4
|
+
data.tar.gz: 668e020302bd7472c9f997bf511f9492d0631265e53727b580ff45ed3a1c39a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e4d37b6a7f25c6704ff4e4fce1184e69f8daace1f36e99c330985e6f4f61b1fc4fc2b1927dffd923c7d9bf95fb8009fdcebbd8c085efcd034ad93d8ee91014b0
|
|
7
|
+
data.tar.gz: 8548e4b4ea99a0ff40417f30f23ace3dcd819d2176c98f47e5ec8e7e3b973a0695b9995d87235e3b085c2853dbc005cbb4f281f9901a76567cb9278c48926939
|
data/ext/leptris/native/native.c
CHANGED
|
@@ -135,6 +135,9 @@ static VALUE c_iteration_scope;
|
|
|
135
135
|
static VALUE c_leptris_error;
|
|
136
136
|
static VALUE c_b_document, c_b_freed, c_ffi_pointer;
|
|
137
137
|
static ID id_ptr_new, id_freed_new, id_alive;
|
|
138
|
+
static ID id_iv_c_address, id_iv_document, id_iv_parent;
|
|
139
|
+
static ID id_iv_structure_memoizable, id_iv_native_fast;
|
|
140
|
+
static ID id_iv_pub_document, id_iv_addr_reads_fast, id_iv_node_type;
|
|
138
141
|
static void check_status_c(int st);
|
|
139
142
|
|
|
140
143
|
#define NT_ELEMENT 0
|
|
@@ -839,8 +842,38 @@ struct trav_state {
|
|
|
839
842
|
VALUE err;
|
|
840
843
|
void *self_ptr;
|
|
841
844
|
int for_visit;
|
|
845
|
+
/* Hoisted per-walk state (was re-resolved per node): the
|
|
846
|
+
* document's wrapper cache and the iteration-scope class
|
|
847
|
+
* check. #312 item 1. */
|
|
848
|
+
VALUE cache;
|
|
849
|
+
VALUE klass_memo_flag;
|
|
842
850
|
};
|
|
843
851
|
|
|
852
|
+
/* Construct-or-fetch the binding wrapper for node_ptr against the
|
|
853
|
+
* per-walk hoisted cache (#312 item 1): static-ID ivar writes (no
|
|
854
|
+
* per-call string interning), the scope class check precomputed. */
|
|
855
|
+
static VALUE trav_wrapper_for(struct trav_state *st, void *node_ptr,
|
|
856
|
+
int kind)
|
|
857
|
+
{
|
|
858
|
+
VALUE key = ULL2NUM((uint64_t)(uintptr_t)node_ptr);
|
|
859
|
+
VALUE node = rb_hash_aref(st->cache, key);
|
|
860
|
+
if (!NIL_P(node)) return node;
|
|
861
|
+
|
|
862
|
+
node = rb_obj_alloc(binding_klass_for(kind));
|
|
863
|
+
rb_ivar_set(node, id_iv_c_address, key);
|
|
864
|
+
rb_ivar_set(node, id_iv_document, st->document);
|
|
865
|
+
rb_ivar_set(node, id_iv_parent, Qnil);
|
|
866
|
+
VALUE fast = st->klass_memo_flag;
|
|
867
|
+
rb_ivar_set(node, id_iv_structure_memoizable, fast);
|
|
868
|
+
rb_ivar_set(node, id_iv_native_fast, fast);
|
|
869
|
+
rb_ivar_set(node, id_iv_pub_document,
|
|
870
|
+
fast == Qtrue ? st->document : Qnil);
|
|
871
|
+
rb_ivar_set(node, id_iv_addr_reads_fast, Qtrue);
|
|
872
|
+
rb_ivar_set(node, id_iv_node_type, INT2FIX(kind));
|
|
873
|
+
rb_hash_aset(st->cache, key, node);
|
|
874
|
+
return node;
|
|
875
|
+
}
|
|
876
|
+
|
|
844
877
|
static VALUE trav_yield_one(VALUE arg)
|
|
845
878
|
{
|
|
846
879
|
return rb_yield(arg);
|
|
@@ -849,33 +882,13 @@ static VALUE trav_yield_one(VALUE arg)
|
|
|
849
882
|
static int trav_cb(void *node_ptr, void *user)
|
|
850
883
|
{
|
|
851
884
|
struct trav_state *st = user;
|
|
852
|
-
VALUE
|
|
885
|
+
VALUE node;
|
|
853
886
|
int kind, state;
|
|
854
887
|
|
|
855
888
|
if (st->err != Qnil)
|
|
856
889
|
return 1;
|
|
857
890
|
kind = f_node_type(node_ptr);
|
|
858
|
-
|
|
859
|
-
key = ULL2NUM((uint64_t)(uintptr_t)node_ptr);
|
|
860
|
-
node = rb_hash_aref(cache, key);
|
|
861
|
-
if (NIL_P(node)) {
|
|
862
|
-
node = rb_obj_alloc(binding_klass_for(kind));
|
|
863
|
-
rb_iv_set(node, "@c_address", key);
|
|
864
|
-
rb_iv_set(node, "@document", st->document);
|
|
865
|
-
rb_iv_set(node, "@parent", Qnil);
|
|
866
|
-
if (rb_obj_class(st->document) == c_iteration_scope) {
|
|
867
|
-
rb_iv_set(node, "@structure_memoizable", Qfalse);
|
|
868
|
-
rb_iv_set(node, "@native_fast", Qfalse);
|
|
869
|
-
rb_iv_set(node, "@pub_document", Qnil);
|
|
870
|
-
} else {
|
|
871
|
-
rb_iv_set(node, "@structure_memoizable", Qtrue);
|
|
872
|
-
rb_iv_set(node, "@native_fast", Qtrue);
|
|
873
|
-
rb_iv_set(node, "@pub_document", st->document);
|
|
874
|
-
}
|
|
875
|
-
rb_iv_set(node, "@addr_reads_fast", Qtrue);
|
|
876
|
-
rb_iv_set(node, "@node_type", INT2FIX(kind));
|
|
877
|
-
rb_hash_aset(cache, key, node);
|
|
878
|
-
}
|
|
891
|
+
node = trav_wrapper_for(st, node_ptr, kind);
|
|
879
892
|
rb_protect(trav_yield_one, node, &state);
|
|
880
893
|
if (state) {
|
|
881
894
|
st->err = rb_errinfo();
|
|
@@ -894,6 +907,9 @@ static VALUE nf_traverse_binding(VALUE self, VALUE document,
|
|
|
894
907
|
st.document = document;
|
|
895
908
|
st.err = Qnil;
|
|
896
909
|
st.self_ptr = (void *)(uintptr_t)NUM2ULL(addr);
|
|
910
|
+
st.cache = binding_cache_of(document);
|
|
911
|
+
st.klass_memo_flag =
|
|
912
|
+
rb_obj_class(document) == c_iteration_scope ? Qfalse : Qtrue;
|
|
897
913
|
st.for_visit = 0;
|
|
898
914
|
f_node_traverse(st.self_ptr, 1 /* TRAVERSE_POST_ORDER */,
|
|
899
915
|
trav_cb, &st);
|
|
@@ -922,33 +938,13 @@ static void visit_cb(void *user, void *node_ptr, int entering,
|
|
|
922
938
|
* happens after the walk, same observable outcome. */
|
|
923
939
|
struct trav_state *st = user;
|
|
924
940
|
struct visit_yield_args va;
|
|
925
|
-
VALUE
|
|
941
|
+
VALUE node;
|
|
926
942
|
int kind, state;
|
|
927
943
|
|
|
928
944
|
if (st->err != Qnil)
|
|
929
945
|
return;
|
|
930
946
|
kind = f_node_type(node_ptr);
|
|
931
|
-
|
|
932
|
-
key = ULL2NUM((uint64_t)(uintptr_t)node_ptr);
|
|
933
|
-
node = rb_hash_aref(cache, key);
|
|
934
|
-
if (NIL_P(node)) {
|
|
935
|
-
node = rb_obj_alloc(binding_klass_for(kind));
|
|
936
|
-
rb_iv_set(node, "@c_address", key);
|
|
937
|
-
rb_iv_set(node, "@document", st->document);
|
|
938
|
-
rb_iv_set(node, "@parent", Qnil);
|
|
939
|
-
if (rb_obj_class(st->document) == c_iteration_scope) {
|
|
940
|
-
rb_iv_set(node, "@structure_memoizable", Qfalse);
|
|
941
|
-
rb_iv_set(node, "@native_fast", Qfalse);
|
|
942
|
-
rb_iv_set(node, "@pub_document", Qnil);
|
|
943
|
-
} else {
|
|
944
|
-
rb_iv_set(node, "@structure_memoizable", Qtrue);
|
|
945
|
-
rb_iv_set(node, "@native_fast", Qtrue);
|
|
946
|
-
rb_iv_set(node, "@pub_document", st->document);
|
|
947
|
-
}
|
|
948
|
-
rb_iv_set(node, "@addr_reads_fast", Qtrue);
|
|
949
|
-
rb_iv_set(node, "@node_type", INT2FIX(kind));
|
|
950
|
-
rb_hash_aset(cache, key, node);
|
|
951
|
-
}
|
|
947
|
+
node = trav_wrapper_for(st, node_ptr, kind);
|
|
952
948
|
va.node = node;
|
|
953
949
|
va.entering = entering ? Qtrue : Qfalse;
|
|
954
950
|
va.depth = INT2NUM(depth);
|
|
@@ -966,6 +962,9 @@ static VALUE nf_visit_binding(VALUE self, VALUE document, VALUE addr)
|
|
|
966
962
|
st.document = document;
|
|
967
963
|
st.err = Qnil;
|
|
968
964
|
st.self_ptr = (void *)(uintptr_t)NUM2ULL(addr);
|
|
965
|
+
st.cache = binding_cache_of(document);
|
|
966
|
+
st.klass_memo_flag =
|
|
967
|
+
rb_obj_class(document) == c_iteration_scope ? Qfalse : Qtrue;
|
|
969
968
|
st.for_visit = 1;
|
|
970
969
|
f_node_visit(st.self_ptr, visit_cb, &st);
|
|
971
970
|
if (st.err != Qnil)
|
|
@@ -2150,6 +2149,34 @@ static VALUE nf_plan_structs_typed_p(VALUE self)
|
|
|
2150
2149
|
return Qtrue;
|
|
2151
2150
|
}
|
|
2152
2151
|
|
|
2152
|
+
/* ---- Bulk attribute rows (leptris-ruby#278) ----------------------
|
|
2153
|
+
* One C crossing per element: walks the attribute chain and
|
|
2154
|
+
* returns a flat [name, value, address, ...] array. Names
|
|
2155
|
+
* interned (they repeat), values fresh UTF-8 strings, addresses
|
|
2156
|
+
* as Integers for Attr c_handle reconstruction. Identical data
|
|
2157
|
+
* to the per-attribute FFI chain (first/next/get_name/get_value,
|
|
2158
|
+
* 4 crossings each) — the win amplifies with attribute density
|
|
2159
|
+
* (40-attr elements: ~7x on the listing). */
|
|
2160
|
+
static VALUE nf_attribute_rows(VALUE self, VALUE document, VALUE addr)
|
|
2161
|
+
{
|
|
2162
|
+
(void)self;
|
|
2163
|
+
(void)document;
|
|
2164
|
+
void *node = (void *)(uintptr_t)NUM2ULL(addr);
|
|
2165
|
+
VALUE out = rb_ary_new();
|
|
2166
|
+
if (f_node_type(node) != WS_NODE_ELEMENT) return out;
|
|
2167
|
+
|
|
2168
|
+
for (void *a = f_attr_first(node); a; a = f_attr_next(a)) {
|
|
2169
|
+
const char *an = f_attr_name(a);
|
|
2170
|
+
const char *av = f_attr_value(node, a);
|
|
2171
|
+
rb_ary_push(out, an ? rb_enc_interned_str(an, strlen(an),
|
|
2172
|
+
rb_utf8_encoding())
|
|
2173
|
+
: Qnil);
|
|
2174
|
+
rb_ary_push(out, av ? rb_utf8_str_new_cstr(av) : Qnil);
|
|
2175
|
+
rb_ary_push(out, ULL2NUM((uintptr_t)a));
|
|
2176
|
+
}
|
|
2177
|
+
return out;
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2153
2180
|
static VALUE nf_plan_structs(VALUE self, VALUE document, VALUE addr,
|
|
2154
2181
|
VALUE spec)
|
|
2155
2182
|
{
|
|
@@ -2620,6 +2647,14 @@ LEPTRIS_INIT_EXPORT void Init_native(void)
|
|
|
2620
2647
|
id_iv_c_address = rb_intern("@c_address");
|
|
2621
2648
|
id_iv_native_cache = rb_intern("@native_cache");
|
|
2622
2649
|
id_iv_binding_cache = rb_intern("@wrapper_cache");
|
|
2650
|
+
id_iv_c_address = rb_intern("@c_address");
|
|
2651
|
+
id_iv_document = rb_intern("@document");
|
|
2652
|
+
id_iv_parent = rb_intern("@parent");
|
|
2653
|
+
id_iv_structure_memoizable = rb_intern("@structure_memoizable");
|
|
2654
|
+
id_iv_native_fast = rb_intern("@native_fast");
|
|
2655
|
+
id_iv_pub_document = rb_intern("@pub_document");
|
|
2656
|
+
id_iv_addr_reads_fast = rb_intern("@addr_reads_fast");
|
|
2657
|
+
id_iv_node_type = rb_intern("@node_type");
|
|
2623
2658
|
id_iv_version = rb_intern("@version");
|
|
2624
2659
|
id_iv_readonly = rb_intern("@readonly");
|
|
2625
2660
|
id_address = rb_intern("address");
|
|
@@ -2732,6 +2767,8 @@ LEPTRIS_INIT_EXPORT void Init_native(void)
|
|
|
2732
2767
|
nf_attribute_pairs, 2);
|
|
2733
2768
|
rb_define_module_function(m_native, "plan_structs",
|
|
2734
2769
|
nf_plan_structs, 3);
|
|
2770
|
+
rb_define_module_function(m_native, "attribute_rows",
|
|
2771
|
+
nf_attribute_rows, 2);
|
|
2735
2772
|
rb_define_module_function(m_native, "plan_structs_typed?",
|
|
2736
2773
|
nf_plan_structs_typed_p, 0);
|
|
2737
2774
|
rb_define_module_function(m_native, "doc_handle_attach",
|
data/lib/leptris/version.rb
CHANGED
data/lib/leptris/xml/element.rb
CHANGED
|
@@ -311,7 +311,11 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
311
311
|
|
|
312
312
|
def attribute_nodes
|
|
313
313
|
return @attribute_nodes if memo_hit?(@attribute_nodes_version)
|
|
314
|
-
result =
|
|
314
|
+
result = if NATIVE_ATTR_ROWS && @c_address && @document
|
|
315
|
+
attribute_rows_native
|
|
316
|
+
else
|
|
317
|
+
each_attribute.to_a
|
|
318
|
+
end
|
|
315
319
|
if @document
|
|
316
320
|
@attribute_nodes = result
|
|
317
321
|
@attribute_nodes_version = @document.version
|
|
@@ -319,6 +323,26 @@ class Leptris::XML::Element < Leptris::XML::Node
|
|
|
319
323
|
result
|
|
320
324
|
end
|
|
321
325
|
|
|
326
|
+
# One C crossing per element (leptris-ruby#278): the native face
|
|
327
|
+
# walks the attribute chain and returns flat [name, value,
|
|
328
|
+
# address] triples; the Attr value objects are minted from them
|
|
329
|
+
# with zero further engine crossings — identical objects to
|
|
330
|
+
# each_attribute. The win amplifies with attribute density
|
|
331
|
+
# (40-attr elements list ~7x faster than the chain).
|
|
332
|
+
def attribute_rows_native
|
|
333
|
+
::Leptris::XML::Native.attribute_rows(@document, @c_address)
|
|
334
|
+
.each_slice(3)
|
|
335
|
+
.map do |name, value, handle|
|
|
336
|
+
::Leptris::XML::Attr.new(name, value, self,
|
|
337
|
+
c_handle: ::FFI::Pointer.new(handle))
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
NATIVE_ATTR_ROWS =
|
|
342
|
+
defined?(::Leptris::XML::Native) &&
|
|
343
|
+
::Leptris::XML::Native.respond_to?(:attribute_rows)
|
|
344
|
+
private_constant :NATIVE_ATTR_ROWS
|
|
345
|
+
|
|
322
346
|
# The element's own namespace prefix (e.g. "foo" for <foo:child/>),
|
|
323
347
|
# or nil when the element has none.
|
|
324
348
|
def prefix
|
data/lib/leptris/xml/native.so
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: leptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.222.
|
|
4
|
+
version: 1.9.222.3
|
|
5
5
|
platform: arm-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|