Reduce unnecessary COW on Vector by make writing explicit

This commit makes operator[] on Vector const and adds a write proxy to it.  From
now on writes to Vectors need to happen through the .write proxy. So for
instance:

Vector<int> vec;
vec.push_back(10);
std::cout << vec[0] << std::endl;
vec.write[0] = 20;

Failing to use the .write proxy will cause a compilation error.

In addition COWable datatypes can now embed a CowData pointer to their data.
This means that String, CharString, and VMap no longer use or derive from
Vector.

_ALWAYS_INLINE_ and _FORCE_INLINE_ are now equivalent for debug and non-debug
builds. This is a lot faster for Vector in the editor and while running tests.
The reason why this difference used to exist is because force-inlined methods
used to give a bad debugging experience. After extensive testing with modern
compilers this is no longer the case.
This commit is contained in:
Hein-Pieter van Braam 2018-07-25 03:11:03 +02:00
parent 9423f23ffb
commit 0e29f7974b
228 changed files with 2200 additions and 2082 deletions

View file

@ -785,8 +785,8 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(codegen.opcodes.size() + 3);
codegen.opcodes[jump_fail_pos] = codegen.opcodes.size();
codegen.opcodes[jump_fail_pos2] = codegen.opcodes.size();
codegen.opcodes.write[jump_fail_pos] = codegen.opcodes.size();
codegen.opcodes.write[jump_fail_pos2] = codegen.opcodes.size();
codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_FALSE);
codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
@ -818,8 +818,8 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(codegen.opcodes.size() + 3);
codegen.opcodes[jump_success_pos] = codegen.opcodes.size();
codegen.opcodes[jump_success_pos2] = codegen.opcodes.size();
codegen.opcodes.write[jump_success_pos] = codegen.opcodes.size();
codegen.opcodes.write[jump_success_pos2] = codegen.opcodes.size();
codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TRUE);
codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
@ -850,7 +850,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
int jump_past_pos = codegen.opcodes.size();
codegen.opcodes.push_back(0);
codegen.opcodes[jump_fail_pos] = codegen.opcodes.size();
codegen.opcodes.write[jump_fail_pos] = codegen.opcodes.size();
res = _parse_expression(codegen, on->arguments[2], p_stack_level);
if (res < 0)
return res;
@ -859,7 +859,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
codegen.opcodes.push_back(res);
codegen.opcodes[jump_past_pos] = codegen.opcodes.size();
codegen.opcodes.write[jump_past_pos] = codegen.opcodes.size();
return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
@ -1361,10 +1361,10 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(break_addr);
codegen.opcodes[continue_addr + 1] = codegen.opcodes.size();
codegen.opcodes.write[continue_addr + 1] = codegen.opcodes.size();
}
codegen.opcodes[break_addr + 1] = codegen.opcodes.size();
codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size();
} break;
@ -1393,16 +1393,16 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
int end_addr = codegen.opcodes.size();
codegen.opcodes.push_back(0);
codegen.opcodes[else_addr] = codegen.opcodes.size();
codegen.opcodes.write[else_addr] = codegen.opcodes.size();
Error err = _parse_block(codegen, cf->body_else, p_stack_level, p_break_addr, p_continue_addr);
if (err)
return err;
codegen.opcodes[end_addr] = codegen.opcodes.size();
codegen.opcodes.write[end_addr] = codegen.opcodes.size();
} else {
//end without else
codegen.opcodes[else_addr] = codegen.opcodes.size();
codegen.opcodes.write[else_addr] = codegen.opcodes.size();
}
} break;
@ -1453,7 +1453,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(continue_pos);
codegen.opcodes[break_pos + 1] = codegen.opcodes.size();
codegen.opcodes.write[break_pos + 1] = codegen.opcodes.size();
codegen.pop_stack_identifiers();
@ -1479,7 +1479,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
codegen.opcodes.push_back(continue_addr);
codegen.opcodes[break_addr + 1] = codegen.opcodes.size();
codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size();
} break;
case GDScriptParser::ControlFlowNode::CF_SWITCH: {
@ -1689,7 +1689,7 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
gdfunc->rpc_mode = p_func->rpc_mode;
gdfunc->argument_types.resize(p_func->argument_types.size());
for (int i = 0; i < p_func->argument_types.size(); i++) {
gdfunc->argument_types[i] = _gdtype_from_datatype(p_func->argument_types[i]);
gdfunc->argument_types.write[i] = _gdtype_from_datatype(p_func->argument_types[i]);
}
gdfunc->return_type = _gdtype_from_datatype(p_func->return_type);
} else {
@ -1708,11 +1708,11 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
if (codegen.constant_map.size()) {
gdfunc->_constant_count = codegen.constant_map.size();
gdfunc->constants.resize(codegen.constant_map.size());
gdfunc->_constants_ptr = &gdfunc->constants[0];
gdfunc->_constants_ptr = gdfunc->constants.ptrw();
const Variant *K = NULL;
while ((K = codegen.constant_map.next(K))) {
int idx = codegen.constant_map[*K];
gdfunc->constants[idx] = *K;
gdfunc->constants.write[idx] = *K;
}
} else {
@ -1726,7 +1726,7 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
gdfunc->_global_names_ptr = &gdfunc->global_names[0];
for (Map<StringName, int>::Element *E = codegen.name_map.front(); E; E = E->next()) {
gdfunc->global_names[E->get()] = E->key();
gdfunc->global_names.write[E->get()] = E->key();
}
gdfunc->_global_names_count = gdfunc->global_names.size();
@ -1741,7 +1741,7 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
gdfunc->named_globals.resize(codegen.named_globals.size());
gdfunc->_named_globals_ptr = gdfunc->named_globals.ptr();
for (int i = 0; i < codegen.named_globals.size(); i++) {
gdfunc->named_globals[i] = codegen.named_globals[i];
gdfunc->named_globals.write[i] = codegen.named_globals[i];
}
gdfunc->_named_globals_count = gdfunc->named_globals.size();
}