History

Fix performance issue regarding all built-in types type descriptors. Check in md5sum program written entirely in limbo.

arr committed 10 years ago

Commit 754ca821 parent 096b0c72 files · +267 −14Browse files

Unified · Split

2 files
  1. limbo/md5sum.b +197 −0
  2. src/vm/vm_memory.cpp +70 −14
limbo/md5sum.b+197−0
@@ -0,0 +1,197 @@
1+implement Exec;
2+
3+include "sys.m";
4+include "Exec.m";
5+
6+sys : Sys;
7+
8+block_size : con 64;
9+max_32 : con int 16rffffffff;
10+
11+shift_map := array [] of {
12+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
13+ 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
14+ 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
15+ 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
16+
17+sine_table := array [] of {
18+ int 16rd76aa478, int 16re8c7b756, int 16r242070db, int 16rc1bdceee,
19+ int 16rf57c0faf, int 16r4787c62a, int 16ra8304613, int 16rfd469501,
20+ int 16r698098d8, int 16r8b44f7af, int 16rffff5bb1, int 16r895cd7be,
21+ int 16r6b901122, int 16rfd987193, int 16ra679438e, int 16r49b40821,
22+ int 16rf61e2562, int 16rc040b340, int 16r265e5a51, int 16re9b6c7aa,
23+ int 16rd62f105d, int 16r02441453, int 16rd8a1e681, int 16re7d3fbc8,
24+ int 16r21e1cde6, int 16rc33707d6, int 16rf4d50d87, int 16r455a14ed,
25+ int 16ra9e3e905, int 16rfcefa3f8, int 16r676f02d9, int 16r8d2a4c8a,
26+ int 16rfffa3942, int 16r8771f681, int 16r6d9d6122, int 16rfde5380c,
27+ int 16ra4beea44, int 16r4bdecfa9, int 16rf6bb4b60, int 16rbebfbc70,
28+ int 16r289b7ec6, int 16reaa127fa, int 16rd4ef3085, int 16r04881d05,
29+ int 16rd9d4d039, int 16re6db99e5, int 16r1fa27cf8, int 16rc4ac5665,
30+ int 16rf4292244, int 16r432aff97, int 16rab9423a7, int 16rfc93a039,
31+ int 16r655b59c3, int 16r8f0ccc92, int 16rffeff47d, int 16r85845dd1,
32+ int 16r6fa87e4f, int 16rfe2ce6e0, int 16ra3014314, int 16r4e0811a1,
33+ int 16rf7537e82, int 16rbd3af235, int 16r2ad7d2bb, int 16reb86d391};
34+
35+leftrotate(x, c : int) : int
36+{
37+ # Limbo doesn't have an unsigned int so all right
38+ # shifts are arithmetic, not logical.
39+ addMask := 0;
40+ x1 := x;
41+ if (x1 < 0)
42+ {
43+ x1 = x1 & 16r7fffffff;
44+ addMask = 2 ** (c - 1);
45+ }
46+
47+ return (x << c) | (x1 >> (32 - c)) | addMask;
48+}
49+
50+md5_acc(block: array of byte, result: array of int)
51+{
52+ a := result[0];
53+ b := result[1];
54+ c := result[2];
55+ d := result[3];
56+
57+ for (i := 0; i < block_size; i++)
58+ {
59+ f : int;
60+ g : int;
61+ case i
62+ {
63+ 0 to 15 =>
64+ f = (b & c) | ((max_32 ^ b) & d);
65+ g = i;
66+ 16 to 31 =>
67+ f = (b & d) | (c & (max_32 ^ d));
68+ g = ((5 * i) + 1) % 16;
69+ 32 to 47 =>
70+ f = b ^ (c ^ d);
71+ g = ((3 * i) + 5) % 16;
72+ 48 to 63 =>
73+ f = c ^ (b | (max_32 ^ d));
74+ g = (7 * i) % 16;
75+ }
76+
77+ tmp := d;
78+ d = c;
79+ c = b;
80+ m := block[(g * 4):];
81+ v := int m[0] | (int m[1] << 8) | (int m[2] << 16) | (int m[3] << 24);
82+ b = b + leftrotate((a + f + sine_table[i] + v), shift_map[i]);
83+ a = tmp;
84+ }
85+
86+ result[0] += a;
87+ result[1] += b;
88+ result[2] += c;
89+ result[3] += d;
90+}
91+
92+pad_block(block: array of byte, curr_block_size: int, msg_size_bytes: big): array of byte
93+{
94+ if (curr_block_size > len(block) || len(block) != block_size) {
95+ raise "Invalid block or pad size";
96+ }
97+
98+ # Zero out the excess block space
99+ for (i := curr_block_size; i < len(block); i++) {
100+ block[i] = byte 0;
101+ }
102+
103+ aux_block : array of byte;
104+ pad_count := block_size - curr_block_size;
105+
106+ # Check if there is room for the last bit and message size
107+ if (pad_count < 9) {
108+ aux_block = array [block_size] of byte;
109+ }
110+
111+ # Set the last bit
112+ if (pad_count < 1) {
113+ aux_block[0] = byte 16r80;
114+ } else {
115+ block[curr_block_size] = byte 16r80;
116+ pad_count--;
117+ curr_block_size++;
118+ }
119+
120+ # Set the message size in bits
121+ msg_size_bits_target : array of byte;
122+ msg_size_bits := (msg_size_bytes * big 8);
123+ if (pad_count < 8) {
124+ msg_size_bits_target = aux_block[56:];
125+ } else {
126+ msg_size_bits_target = block[56:];
127+ }
128+
129+ mask : con byte 16rff;
130+ msg_size_bits_target[0] = byte msg_size_bits & mask;
131+ msg_size_bits_target[1] = byte (msg_size_bits >> 8) & mask;
132+ msg_size_bits_target[2] = byte (msg_size_bits >> 16) & mask;
133+ msg_size_bits_target[3] = byte (msg_size_bits >> 24) & mask;
134+ msg_size_bits_target[4] = byte (msg_size_bits >> 32) & mask;
135+ msg_size_bits_target[5] = byte (msg_size_bits >> 40) & mask;
136+ msg_size_bits_target[6] = byte (msg_size_bits >> 48) & mask;
137+ msg_size_bits_target[7] = byte (msg_size_bits >> 56) & mask;
138+
139+ return aux_block;
140+}
141+
142+print_block(name: string, block: array of byte)
143+{
144+ sys->print("%s\n", name);
145+
146+ for (i := 0; i < len(block); i++)
147+ {
148+ if (i != 0 && i % 16 == 0)
149+ sys->print("\n");
150+
151+ sys->print("%d ", int block[i]);
152+ }
153+ sys->print("\n");
154+}
155+
156+init(args: list of string)
157+{
158+ sys = load Sys Sys->PATH;
159+ if (len(args) == 1) {
160+ sys->print("Usage: md5sum <file>");
161+ return;
162+ }
163+
164+ fd := sys->open(hd tl args, sys->OREAD);
165+ if (fd == nil) {
166+ raise "Failed to open file";
167+ }
168+
169+ checksum := array [] of {
170+ int 16r67452301,
171+ int 16refcdab89,
172+ int 16r98badcfe,
173+ int 16r10325476 };
174+
175+ msg_size_bytes := big 0;
176+ block := array [block_size] of byte;
177+ c := sys->read(fd, block, block_size);
178+ while (c == block_size) {
179+ msg_size_bytes += big c;
180+ md5_acc(block, checksum);
181+ c = sys->read(fd, block, block_size);
182+ }
183+
184+ msg_size_bytes += big c;
185+
186+ # Pad the last block
187+ aux_block := pad_block(block, c, msg_size_bytes);
188+ md5_acc(block, checksum);
189+ if (aux_block != nil) {
190+ md5_acc(aux_block, checksum);
191+ }
192+
193+ for (i := 0; i < len (checksum); ++i) {
194+ v := checksum[i];
195+ sys->print("%02x%02x%02x%02x", v & 16rff, (v >> 8) & 16rff, (v >> 16) & 16rff, (v >> 24) & 16rff);
196+ }
197+}
src/vm/vm_memory.cpp+70−14
@@ -355,46 +355,102 @@ namespace · 354 unmodified lines
355355 }
356356
357357 template<>
358−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<byte_t>() { return{ &hidden_type_desc::byte, hidden_type_desc::deleter }; }
358+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<byte_t>()
359+{
360+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::byte, hidden_type_desc::deleter };
361+ return t;
362+}
359363
360364 template<>
361−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<short_word_t>() { return{ &hidden_type_desc::short_word, hidden_type_desc::deleter }; }
365+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<short_word_t>()
366+{
367+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::short_word, hidden_type_desc::deleter };
368+ return t;
369+}
362370
363371 template<>
364−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<word_t>() { return{ &hidden_type_desc::word, hidden_type_desc::deleter }; }
372+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<word_t>()
373+{
374+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::word, hidden_type_desc::deleter };
375+ return t;
376+}
365377
366378 template<>
367−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<short_real_t>() { return{ &hidden_type_desc::short_real, hidden_type_desc::deleter }; }
379+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<short_real_t>()
380+{
381+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::short_real, hidden_type_desc::deleter };
382+ return t;
383+}
368384
369385 template<>
370−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<real_t>() { return{ &hidden_type_desc::real, hidden_type_desc::deleter }; }
386+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<real_t>()
387+{
388+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::real, hidden_type_desc::deleter };
389+ return t;
390+}
371391
372392 template<>
373−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<big_t>() { return{ &hidden_type_desc::big, hidden_type_desc::deleter }; }
393+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<big_t>()
394+{
395+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::big, hidden_type_desc::deleter };
396+ return t;
397+}
374398
375399 template<>
376−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<pointer_t>() { return{ &hidden_type_desc::pointer, hidden_type_desc::deleter }; }
400+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<pointer_t>()
401+{
402+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::pointer, hidden_type_desc::deleter };
403+ return t;
404+}
377405
378406 template<>
379−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_array_t>() { return{ &hidden_type_desc::vm_array, hidden_type_desc::deleter }; }
407+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_array_t>()
408+{
409+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::vm_array, hidden_type_desc::deleter };
410+ return t;
411+}
380412
381413 template<>
382−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_list_t>() { return{ &hidden_type_desc::vm_list, hidden_type_desc::deleter }; }
414+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_list_t>()
415+{
416+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::vm_list, hidden_type_desc::deleter };
417+ return t;
418+}
383419
384420 template<>
385−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_channel_t>() { return{ &hidden_type_desc::vm_channel, hidden_type_desc::deleter }; }
421+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_channel_t>()
422+{
423+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::vm_channel, hidden_type_desc::deleter };
424+ return t;
425+}
386426
387427 template<>
388−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_string_t>() { return{ &hidden_type_desc::vm_string, hidden_type_desc::deleter }; }
428+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_string_t>()
429+{
430+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::vm_string, hidden_type_desc::deleter };
431+ return t;
432+}
389433
390434 template<>
391−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_module_ref_t>() { return{ &hidden_type_desc::vm_module_ref, hidden_type_desc::deleter }; }
435+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_module_ref_t>()
436+{
437+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::vm_module_ref, hidden_type_desc::deleter };
438+ return t;
439+}
392440
393441 template<>
394−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_stack_t>() { return{ &hidden_type_desc::vm_stack, hidden_type_desc::deleter }; }
442+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_stack_t>()
443+{
444+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::vm_stack, hidden_type_desc::deleter };
445+ return t;
446+}
395447
396448 template<>
397−static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_thread_t>() { return{ &hidden_type_desc::vm_thread, hidden_type_desc::deleter }; }
449+static std::shared_ptr<const type_descriptor_t> intrinsic_type_desc::type<vm_thread_t>()
450+{
451+ static std::shared_ptr<const type_descriptor_t> t = { &hidden_type_desc::vm_thread, hidden_type_desc::deleter };
452+ return t;
453+}
398454
399455 vm_alloc_instance_finalizer_t type_descriptor_t::no_finalizer = nullptr;
400456