racer-rb 0.1.0
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 +7 -0
- data/.rubocop.yml +9 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/LICENSE.txt +21 -0
- data/README.md +93 -0
- data/Rakefile +23 -0
- data/ext/racer/extconf.rb +14 -0
- data/ext/racer/racer.cc +999 -0
- data/ext/racer/racer.hh +37 -0
- data/ext/racer/tiny_queue.cc +103 -0
- data/ext/racer/tiny_queue.hh +39 -0
- data/ext/racer/traces.cc +70 -0
- data/ext/racer/traces.hh +95 -0
- data/ext/racer/worker.cc +188 -0
- data/ext/racer/worker.hh +15 -0
- data/lib/racer/agent.rb +250 -0
- data/lib/racer/collectors/rbs_collector.rb +645 -0
- data/lib/racer/minitest.rb +20 -0
- data/lib/racer/minitest_plugin.rb +35 -0
- data/lib/racer/rails/railtie.rb +38 -0
- data/lib/racer/rb.rb +2 -0
- data/lib/racer/rspec.rb +19 -0
- data/lib/racer/rspec_plugin.rb +28 -0
- data/lib/racer/trace.rb +121 -0
- data/lib/racer/version.rb +5 -0
- data/lib/racer.rb +40 -0
- data/sig/racer.rbs +4 -0
- metadata +87 -0
data/ext/racer/racer.hh
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#ifndef RACER_H
|
|
2
|
+
#define RACER_H 1
|
|
3
|
+
|
|
4
|
+
#include "ruby.h"
|
|
5
|
+
#include "ruby/ruby.h"
|
|
6
|
+
#include "ruby/debug.h"
|
|
7
|
+
#include "ruby/re.h"
|
|
8
|
+
#include "pthread.h"
|
|
9
|
+
#include "worker.hh"
|
|
10
|
+
#include "tiny_queue.hh"
|
|
11
|
+
#include "traces.hh"
|
|
12
|
+
|
|
13
|
+
struct reg_onig_search_args {
|
|
14
|
+
long pos;
|
|
15
|
+
long range;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Copied from ruby/re.c because the function is not exported in re.h
|
|
19
|
+
static OnigPosition
|
|
20
|
+
reg_onig_search(regex_t *reg, VALUE str, struct re_registers *regs, void *args_ptr)
|
|
21
|
+
{
|
|
22
|
+
struct reg_onig_search_args *args = (struct reg_onig_search_args *)args_ptr;
|
|
23
|
+
const char *ptr;
|
|
24
|
+
long len;
|
|
25
|
+
RSTRING_GETMEM(str, ptr, len);
|
|
26
|
+
|
|
27
|
+
return onig_search(
|
|
28
|
+
reg,
|
|
29
|
+
(UChar *)ptr,
|
|
30
|
+
(UChar *)(ptr + len),
|
|
31
|
+
(UChar *)(ptr + args->pos),
|
|
32
|
+
(UChar *)(ptr + args->range),
|
|
33
|
+
regs,
|
|
34
|
+
ONIG_OPTION_NONE);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#endif /* RACER_H */
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#include "tiny_queue.hh"
|
|
2
|
+
|
|
3
|
+
// Create a queue, return a pointer to tiny_queue_t or NULL on error
|
|
4
|
+
tiny_queue_t *tiny_queue_create()
|
|
5
|
+
{
|
|
6
|
+
struct tiny_queue_t *queue = (struct tiny_queue_t *)malloc(sizeof(struct tiny_queue_t));
|
|
7
|
+
|
|
8
|
+
if (queue == nullptr)
|
|
9
|
+
{
|
|
10
|
+
return nullptr;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
queue->head = nullptr;
|
|
14
|
+
queue->tail = nullptr;
|
|
15
|
+
|
|
16
|
+
if (pthread_mutex_init(&queue->mutex, nullptr) == 0 &&
|
|
17
|
+
pthread_cond_init(&queue->wakeup, nullptr) == 0)
|
|
18
|
+
{
|
|
19
|
+
return queue;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
free(queue);
|
|
23
|
+
return nullptr;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Push a pointer onto the queue, return -1 on error
|
|
27
|
+
int tiny_queue_push(tiny_queue_t *queue, tiny_queue_message_t *x)
|
|
28
|
+
{
|
|
29
|
+
struct tiny_linked_list_t *new_node = (struct tiny_linked_list_t *)malloc(sizeof(struct tiny_linked_list_t));
|
|
30
|
+
|
|
31
|
+
if (new_node == nullptr)
|
|
32
|
+
{
|
|
33
|
+
return -1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
new_node->data = x;
|
|
37
|
+
new_node->next = nullptr;
|
|
38
|
+
|
|
39
|
+
pthread_mutex_lock(&queue->mutex);
|
|
40
|
+
if (queue->head == nullptr && queue->tail == nullptr)
|
|
41
|
+
{
|
|
42
|
+
queue->head = queue->tail = new_node;
|
|
43
|
+
}
|
|
44
|
+
else
|
|
45
|
+
{
|
|
46
|
+
queue->tail->next = new_node;
|
|
47
|
+
queue->tail = new_node;
|
|
48
|
+
}
|
|
49
|
+
pthread_mutex_unlock(&queue->mutex);
|
|
50
|
+
pthread_cond_signal(&queue->wakeup);
|
|
51
|
+
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Pop a pointer from the queue
|
|
56
|
+
void *tiny_queue_pop(tiny_queue_t *queue)
|
|
57
|
+
{
|
|
58
|
+
pthread_mutex_lock(&queue->mutex);
|
|
59
|
+
while (queue->head == nullptr)
|
|
60
|
+
{ // block if buffer is empty
|
|
61
|
+
pthread_cond_wait(&queue->wakeup, &queue->mutex);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
struct tiny_linked_list_t *current_head = queue->head;
|
|
65
|
+
void *data = current_head->data;
|
|
66
|
+
if (queue->head == queue->tail)
|
|
67
|
+
{
|
|
68
|
+
queue->head = queue->tail = nullptr;
|
|
69
|
+
}
|
|
70
|
+
else
|
|
71
|
+
{
|
|
72
|
+
queue->head = queue->head->next;
|
|
73
|
+
}
|
|
74
|
+
free(current_head);
|
|
75
|
+
pthread_mutex_unlock(&queue->mutex);
|
|
76
|
+
|
|
77
|
+
return data;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Destroy the queue with all elements
|
|
81
|
+
int tiny_queue_destroy(tiny_queue_t *queue)
|
|
82
|
+
{
|
|
83
|
+
if (pthread_mutex_destroy(&queue->mutex) != 0 ||
|
|
84
|
+
pthread_cond_destroy(&queue->wakeup) != 0)
|
|
85
|
+
return -1;
|
|
86
|
+
|
|
87
|
+
struct tiny_linked_list_t *node, *next;
|
|
88
|
+
node = queue->head;
|
|
89
|
+
|
|
90
|
+
if (node != nullptr)
|
|
91
|
+
{
|
|
92
|
+
while (node->next != nullptr)
|
|
93
|
+
{
|
|
94
|
+
next = node->next;
|
|
95
|
+
free(node);
|
|
96
|
+
node = next;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
free(queue);
|
|
101
|
+
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Taken from https://github.com/schneems/tiny_queue (MIT Licensed)
|
|
2
|
+
#ifndef __TINY_QUEUE__
|
|
3
|
+
#define __TINY_QUEUE__ 1
|
|
4
|
+
|
|
5
|
+
#include <stdio.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <pthread.h>
|
|
8
|
+
#include <sys/types.h>
|
|
9
|
+
#include <string.h>
|
|
10
|
+
|
|
11
|
+
typedef struct tiny_queue_t {
|
|
12
|
+
struct tiny_linked_list_t* head;
|
|
13
|
+
struct tiny_linked_list_t* tail;
|
|
14
|
+
pthread_mutex_t mutex;
|
|
15
|
+
pthread_cond_t wakeup;
|
|
16
|
+
} tiny_queue_t;
|
|
17
|
+
|
|
18
|
+
typedef struct tiny_queue_message_t {
|
|
19
|
+
int queue_state;
|
|
20
|
+
void* data;
|
|
21
|
+
} tiny_queue_message_t;
|
|
22
|
+
|
|
23
|
+
typedef struct tiny_linked_list_t {
|
|
24
|
+
void *data;
|
|
25
|
+
struct tiny_linked_list_t* next;
|
|
26
|
+
} tiny_linked_list_t;
|
|
27
|
+
|
|
28
|
+
// Create an instance of tiny_queue
|
|
29
|
+
tiny_queue_t* tiny_queue_create();
|
|
30
|
+
|
|
31
|
+
// Push pointer onto tiny_queue, return -1 on error
|
|
32
|
+
int tiny_queue_push(tiny_queue_t *queue, tiny_queue_message_t *x);
|
|
33
|
+
|
|
34
|
+
// Pop pointer from tiny_queue
|
|
35
|
+
void *tiny_queue_pop(tiny_queue_t *queue);
|
|
36
|
+
|
|
37
|
+
// Destroy the queue with all elements
|
|
38
|
+
int tiny_queue_destroy(tiny_queue_t *queue);
|
|
39
|
+
#endif
|
data/ext/racer/traces.cc
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#include "traces.hh"
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
|
|
4
|
+
void free_constant_instance(ConstantInstance& instance) {
|
|
5
|
+
// Name is owned by "Constant" object
|
|
6
|
+
|
|
7
|
+
if(instance.generic_arguments) {
|
|
8
|
+
for(unsigned char i = 0; i < instance.generic_argument_count; ++i) {
|
|
9
|
+
for(auto generic_argument : instance.generic_arguments[i]) {
|
|
10
|
+
free_constant_instance(generic_argument);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
delete[] instance.generic_arguments;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void free_param(Parameter& param) {
|
|
18
|
+
if(param.name) {
|
|
19
|
+
free(param.name);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
free_constant_instance(param.type_name);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void free_block_param(BlockParameter& param) {
|
|
26
|
+
if(param.name) {
|
|
27
|
+
free(param.name);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
for(auto trace : param.block_traces) {
|
|
31
|
+
if(trace) {
|
|
32
|
+
free_trace(trace);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for(auto trace : param.current_block_call_stack) {
|
|
37
|
+
if(trace) {
|
|
38
|
+
free_trace(trace);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void free_trace(ReturnTrace* trace) {
|
|
44
|
+
free_constant_instance(trace->method_owner);
|
|
45
|
+
|
|
46
|
+
if(trace->method_callee.has_value()) {
|
|
47
|
+
free_constant_instance(trace->method_callee.value());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if(trace->method_name) {
|
|
51
|
+
free(trace->method_name);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
free_constant_instance(trace->return_type);
|
|
55
|
+
|
|
56
|
+
for(long i = 0; i < trace->params_size; ++i) {
|
|
57
|
+
free_param(trace->params[i]);
|
|
58
|
+
}
|
|
59
|
+
delete[] trace->params;
|
|
60
|
+
|
|
61
|
+
if(trace->block_param.has_value()) {
|
|
62
|
+
free_block_param(trace->block_param.value());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if(trace->block_self_type.has_value()) {
|
|
66
|
+
free_constant_instance(trace->block_self_type.value());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
delete(trace);
|
|
70
|
+
}
|
data/ext/racer/traces.hh
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
|
|
2
|
+
#ifndef TRACES_H
|
|
3
|
+
#define TRACES_H 1
|
|
4
|
+
|
|
5
|
+
#include <vector>
|
|
6
|
+
#include <optional>
|
|
7
|
+
#include <memory>
|
|
8
|
+
|
|
9
|
+
enum ParamType {
|
|
10
|
+
REQUIRED = 0,
|
|
11
|
+
OPTIONAL = 1,
|
|
12
|
+
REST = 2,
|
|
13
|
+
KEYWORD_REQUIRED = 3,
|
|
14
|
+
KEYWORD_OPTIONAL = 4,
|
|
15
|
+
KEYWORD_REST = 5
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
enum ClassType {
|
|
19
|
+
MODULE = 0,
|
|
20
|
+
CLASS = 1,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
enum MethodKind {
|
|
24
|
+
INSTANCE = 0,
|
|
25
|
+
SINGLETON = 1,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
enum MethodVisibility {
|
|
29
|
+
PUBLIC = 0,
|
|
30
|
+
PRIVATE = 1,
|
|
31
|
+
PROTECTED = 2,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
typedef struct Constant {
|
|
35
|
+
char* name { nullptr };
|
|
36
|
+
bool anonymous { false };
|
|
37
|
+
ClassType type { MODULE };
|
|
38
|
+
std::optional<char*> superclass {};
|
|
39
|
+
std::vector<char*> included_modules {};
|
|
40
|
+
std::vector<char*> prepended_modules {};
|
|
41
|
+
std::vector<char*> extended_modules {};
|
|
42
|
+
} Constant;
|
|
43
|
+
|
|
44
|
+
typedef struct ConstantInstance {
|
|
45
|
+
char* name { nullptr };
|
|
46
|
+
unsigned char generic_argument_count { 0 };
|
|
47
|
+
std::vector<ConstantInstance>* generic_arguments { nullptr };
|
|
48
|
+
bool singleton { false };
|
|
49
|
+
} ConstantInstance;
|
|
50
|
+
|
|
51
|
+
typedef struct Parameter {
|
|
52
|
+
char* name { nullptr };
|
|
53
|
+
ConstantInstance type_name {};
|
|
54
|
+
ParamType param_type { REQUIRED };
|
|
55
|
+
} Parameter;
|
|
56
|
+
|
|
57
|
+
typedef struct ReturnTrace ReturnTrace;
|
|
58
|
+
|
|
59
|
+
typedef struct BlockParameter {
|
|
60
|
+
char* name { nullptr };
|
|
61
|
+
unsigned long tracepoint_id { 0 };
|
|
62
|
+
std::vector<ReturnTrace*> block_traces {};
|
|
63
|
+
std::vector<ReturnTrace*> current_block_call_stack {};
|
|
64
|
+
} BlockParameter;
|
|
65
|
+
|
|
66
|
+
struct ReturnTrace
|
|
67
|
+
{
|
|
68
|
+
ConstantInstance method_owner {};
|
|
69
|
+
// Won't be set if callee is equal to owner
|
|
70
|
+
std::optional<ConstantInstance> method_callee {};
|
|
71
|
+
char *method_name { nullptr };
|
|
72
|
+
MethodKind method_kind { INSTANCE };
|
|
73
|
+
MethodVisibility method_visibility { PUBLIC };
|
|
74
|
+
ConstantInstance return_type {};
|
|
75
|
+
long params_size { 0 };
|
|
76
|
+
Parameter *params { nullptr };
|
|
77
|
+
bool rescued { false };
|
|
78
|
+
|
|
79
|
+
std::vector<std::shared_ptr<Constant>> constant_updates {};
|
|
80
|
+
|
|
81
|
+
std::optional<BlockParameter> block_param {};
|
|
82
|
+
// only relevant for block traces, maybe we could reuse the method_owner Constant but I think it would
|
|
83
|
+
// be even better if we could split those two types anyway
|
|
84
|
+
std::optional<ConstantInstance> block_self_type {};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
void free_constant_instance(ConstantInstance& instance);
|
|
88
|
+
|
|
89
|
+
void free_param(Parameter& param);
|
|
90
|
+
|
|
91
|
+
void free_block_param(BlockParameter& param);
|
|
92
|
+
|
|
93
|
+
void free_trace(ReturnTrace* trace);
|
|
94
|
+
|
|
95
|
+
#endif /* TRACES_H */
|
data/ext/racer/worker.cc
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#include "worker.hh"
|
|
2
|
+
#include "unistd.h"
|
|
3
|
+
#include <sys/socket.h>
|
|
4
|
+
#include <json-c/json.h>
|
|
5
|
+
|
|
6
|
+
void write_constant(json_object* json_array, std::shared_ptr<Constant> constant) {
|
|
7
|
+
json_object_array_add(json_array, json_object_new_string(constant->name));
|
|
8
|
+
json_object_array_add(json_array, json_object_new_boolean(constant->anonymous));
|
|
9
|
+
json_object_array_add(json_array, json_object_new_int(constant->type));
|
|
10
|
+
|
|
11
|
+
if(constant->superclass.has_value()) {
|
|
12
|
+
json_object_array_add(json_array, json_object_new_string(constant->superclass.value()));
|
|
13
|
+
} else {
|
|
14
|
+
json_object_array_add(json_array, json_object_new_null());
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
json_object_array_add(json_array, json_object_new_uint64(constant->included_modules.size()));
|
|
18
|
+
for(auto name : constant->included_modules) {
|
|
19
|
+
json_object_array_add(json_array, json_object_new_string(name));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
json_object_array_add(json_array, json_object_new_uint64(constant->prepended_modules.size()));
|
|
23
|
+
for(auto name : constant->prepended_modules) {
|
|
24
|
+
json_object_array_add(json_array, json_object_new_string(name));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
json_object_array_add(json_array, json_object_new_uint64(constant->extended_modules.size()));
|
|
28
|
+
for(auto name : constant->extended_modules) {
|
|
29
|
+
json_object_array_add(json_array, json_object_new_string(name));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void write_constant_instance(json_object* json_array, ConstantInstance& instance) {
|
|
34
|
+
json_object_array_add(json_array, json_object_new_string(instance.name));
|
|
35
|
+
json_object_array_add(json_array, json_object_new_boolean(instance.singleton));
|
|
36
|
+
json_object_array_add(json_array, json_object_new_uint64(instance.generic_argument_count));
|
|
37
|
+
for(int i = 0; i < instance.generic_argument_count; ++i) {
|
|
38
|
+
json_object_array_add(json_array, json_object_new_uint64(instance.generic_arguments[i].size()));
|
|
39
|
+
for(auto generic_instance : instance.generic_arguments[i]) {
|
|
40
|
+
write_constant_instance(json_array, generic_instance);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
int size_of_constant(std::shared_ptr<Constant> constant) {
|
|
46
|
+
return 7 + constant->included_modules.size() + constant->prepended_modules.size() + constant->extended_modules.size();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
int size_of_constant_updates(std::vector<std::shared_ptr<Constant>> &constant_updates) {
|
|
50
|
+
auto size = 1;
|
|
51
|
+
for(auto constant : constant_updates) {
|
|
52
|
+
size += size_of_constant(constant);
|
|
53
|
+
}
|
|
54
|
+
return size;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
int size_of_constant_instance(ConstantInstance& instance) {
|
|
58
|
+
auto size = 3 + instance.generic_argument_count;
|
|
59
|
+
for(int i = 0; i < instance.generic_argument_count; ++i) {
|
|
60
|
+
for(auto generic_instance : instance.generic_arguments[i]) {
|
|
61
|
+
size += size_of_constant_instance(generic_instance);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return size;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
int size_of_block_trace(ReturnTrace*);
|
|
68
|
+
|
|
69
|
+
int size_of_params(ReturnTrace* trace) {
|
|
70
|
+
auto size = 2 + trace->params_size * 3;
|
|
71
|
+
|
|
72
|
+
if(trace->block_param.has_value()) {
|
|
73
|
+
size += 2;
|
|
74
|
+
for(auto block_trace : (*(trace->block_param)).block_traces) {
|
|
75
|
+
size += size_of_block_trace(block_trace);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return size;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
int size_of_block_trace(ReturnTrace* trace) {
|
|
82
|
+
return 2 + size_of_params(trace);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
void write_params(json_object*, ReturnTrace*);
|
|
86
|
+
|
|
87
|
+
void write_block_trace(json_object* json_array, ReturnTrace* trace) {
|
|
88
|
+
write_constant_instance(json_array, trace->block_self_type.value());
|
|
89
|
+
write_constant_instance(json_array, trace->return_type);
|
|
90
|
+
write_params(json_array, trace);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
void write_params(json_object* json_array, ReturnTrace* trace) {
|
|
94
|
+
json_object_array_add(json_array, json_object_new_int64(trace->params_size));
|
|
95
|
+
|
|
96
|
+
for (long i = 0; i < trace->params_size; ++i)
|
|
97
|
+
{
|
|
98
|
+
auto param = trace->params[i];
|
|
99
|
+
if(param.name) {
|
|
100
|
+
json_object_array_add(json_array, json_object_new_string(param.name));
|
|
101
|
+
} else {
|
|
102
|
+
json_object_array_add(json_array, json_object_new_null());
|
|
103
|
+
}
|
|
104
|
+
json_object_array_add(json_array, json_object_new_int(param.param_type));
|
|
105
|
+
write_constant_instance(json_array, param.type_name);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
json_object_array_add(json_array, json_object_new_boolean(trace->block_param.has_value()));
|
|
109
|
+
|
|
110
|
+
if(trace->block_param.has_value()) {
|
|
111
|
+
auto block_param = *(trace->block_param);
|
|
112
|
+
if(block_param.name) {
|
|
113
|
+
json_object_array_add(json_array, json_object_new_string(block_param.name));
|
|
114
|
+
} else {
|
|
115
|
+
json_object_array_add(json_array, json_object_new_null());
|
|
116
|
+
}
|
|
117
|
+
json_object_array_add(json_array, json_object_new_uint64(block_param.block_traces.size()));
|
|
118
|
+
for(auto block_trace : block_param.block_traces) {
|
|
119
|
+
write_block_trace(json_array, block_trace);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
void *init_worker(void *arg)
|
|
125
|
+
{
|
|
126
|
+
auto *worker_data = static_cast<WorkerData *>(arg);
|
|
127
|
+
auto *tiny_queue = worker_data->queue;
|
|
128
|
+
auto socket_fd = worker_data->socket_fd;
|
|
129
|
+
|
|
130
|
+
// Worker Data is being allocated by the main thread
|
|
131
|
+
free(worker_data);
|
|
132
|
+
|
|
133
|
+
tiny_queue_message_t *message;
|
|
134
|
+
ReturnTrace *trace;
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
while (true)
|
|
138
|
+
{
|
|
139
|
+
message = static_cast<tiny_queue_message_t *>(tiny_queue_pop(tiny_queue));
|
|
140
|
+
if (message->queue_state == 0)
|
|
141
|
+
break;
|
|
142
|
+
|
|
143
|
+
trace = static_cast<ReturnTrace *>(message->data);
|
|
144
|
+
|
|
145
|
+
auto array_size = 2 + size_of_constant_instance(trace->return_type) + size_of_constant_instance(trace->method_owner) + size_of_params(trace) + size_of_constant_updates(trace->constant_updates);
|
|
146
|
+
if(trace->method_callee.has_value()) {
|
|
147
|
+
array_size += size_of_constant_instance(trace->method_callee.value());
|
|
148
|
+
} else {
|
|
149
|
+
array_size += 1;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
auto* json_array = json_object_new_array_ext(array_size);
|
|
153
|
+
|
|
154
|
+
// method_name,return_type,owner_name,owner_type,namespace_size,[path_name,path_type,*],...
|
|
155
|
+
json_object_array_add(json_array, json_object_new_string(trace->method_name));
|
|
156
|
+
json_object_array_add(json_array, json_object_new_int(trace->method_kind));
|
|
157
|
+
json_object_array_add(json_array, json_object_new_int(trace->method_visibility));
|
|
158
|
+
|
|
159
|
+
write_constant_instance(json_array, trace->return_type);
|
|
160
|
+
write_constant_instance(json_array, trace->method_owner);
|
|
161
|
+
if(trace->method_callee.has_value()) {
|
|
162
|
+
write_constant_instance(json_array, trace->method_callee.value());
|
|
163
|
+
} else {
|
|
164
|
+
json_object_array_add(json_array, json_object_new_null());
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
json_object_array_add(json_array, json_object_new_uint64(trace->constant_updates.size()));
|
|
168
|
+
for(auto constant : trace->constant_updates) {
|
|
169
|
+
write_constant(json_array, constant);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
write_params(json_array, trace);
|
|
173
|
+
|
|
174
|
+
auto json_string = json_object_to_json_string_ext(json_array, JSON_C_TO_STRING_PLAIN);
|
|
175
|
+
|
|
176
|
+
if(send(socket_fd, json_string, strlen(json_string) + 1, 0) < 0) {
|
|
177
|
+
perror("socket send");
|
|
178
|
+
return nullptr;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
json_object_put(json_array);
|
|
182
|
+
|
|
183
|
+
free_trace(trace);
|
|
184
|
+
free(message);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return nullptr;
|
|
188
|
+
}
|
data/ext/racer/worker.hh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef WORKER_H
|
|
2
|
+
#define WORKER_H 1
|
|
3
|
+
|
|
4
|
+
#include <stdio.h>
|
|
5
|
+
#include "tiny_queue.hh"
|
|
6
|
+
#include "traces.hh"
|
|
7
|
+
|
|
8
|
+
typedef struct WorkerData {
|
|
9
|
+
tiny_queue_t* queue;
|
|
10
|
+
int socket_fd;
|
|
11
|
+
} WorkerData;
|
|
12
|
+
|
|
13
|
+
void *init_worker(void *);
|
|
14
|
+
|
|
15
|
+
#endif /* WORKER_H */
|