diff -r bb419abf0df4 -r 153d0cafc1fd src/BytecodeCompiler.cpp --- a/src/BytecodeCompiler.cpp Sat Aug 04 21:47:30 2012 -0700 +++ b/src/BytecodeCompiler.cpp Sat Aug 04 23:26:49 2012 -0700 @@ -201,6 +201,8 @@ void BytecodeCompiler::visit(Assignment *node) { + Local type(zone_, node->expression()->type()); + // The first step is three sub-steps: // // (1) Bind the left-hand side. @@ -213,8 +215,12 @@ Variable *var = proxy->binding()->toVariable(); // Bind. - if (var->type()->isReference() || var->type()->isArray()) + if (var->type()->isReference() || + var->type()->isArray() || + var->type()->isStruct()) + { __ get(var); + } // Get the value if needed. if (node->token() != TOK_ASSIGN) { @@ -234,15 +240,16 @@ expr->left()->accept(this); - if (node->token() != TOK_ASSIGN) { + if (node->token() != TOK_ASSIGN) __ dup(); + + if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) __ getfield(expr->fieldIndex(), expr->type()); - } } else { IndexExpression *index = node->lvalue()->toIndexExpression(); __ note_position(index->pos()); - // Note: Eventually, watch out for a whole here. An expression like: + // Note: Eventually, watch out for a hole here. An expression like: // // (a[4] = (5, a = [])) // @@ -252,13 +259,12 @@ index->left()->accept(this); index->right()->accept(this); - if (node->token() != TOK_ASSIGN) { + if (node->token() != TOK_ASSIGN) __ dup2(); + + if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) { __ bounds(); - if (node->type()->isArray()) - __ getarray_o(); - else - __ getarray(node->type()); + __ getarray(index->type()); } } @@ -273,11 +279,16 @@ } // Emit the store. - if (node->expression()->type()->isArray()) { + if (type->isArray()) { // Unlike references, which can only be computed from a NamePRoxy, // arrays can be computed from multiple lvalue types. __ note_position(node->pos()); - __ arraycopy(); + __ copyarray(); + } else if (type->isStruct()) { + // Structs have value semantics, so emit a full copy. We don't break + // this down into u-ops, to avoid unnecessary bytecode explosion. + __ note_position(node->pos()); + __ copystruct(); } else if (node->lvalue()->isNameProxy()) { NameProxy *proxy = node->lvalue()->toNameProxy(); Variable *var = proxy->binding()->toVariable(); @@ -793,7 +804,7 @@ if (node->initialization()) { node->initialization()->accept(this); __ note_position(node->pos()); - __ arraycopy(); + __ copyarray(); } } else if (type->isStruct()) { Local map(zone_, type->newMap());