diff -r 05571208642f -r 387d76b1e981 src/BytecodeCompiler.cpp --- a/src/BytecodeCompiler.cpp Sat Sep 15 13:32:01 2012 -0700 +++ b/src/BytecodeCompiler.cpp Sat Sep 15 17:39:45 2012 -0700 @@ -199,10 +199,18 @@ __ pop(); } +static inline bool +IsCompositeValueType(Type *type) +{ + return type->isStruct() || + (type->isArray() && type->isFixedLength()); +} + void BytecodeCompiler::visit(Assignment *node) { - Local type(zone_, node->expression()->type()); + Local left(zone_, node->type()); + Local right(zone_, node->expression()->type()); // The first step is three sub-steps: // @@ -215,13 +223,12 @@ NameProxy *proxy = node->lvalue()->toNameProxy(); Variable *var = proxy->binding()->toVariable(); - // Bind. - if (var->type()->isReference() || - var->type()->isArray() || - var->type()->isStruct()) - { + // We need to fetch the variable under the following circumstances: + // (1) The variable is a reference, since we'll store into the ref. + // (2) The variable is a fixed array, since we need to copy into it. + // (3) The variable is a struct, since we need to copy into it. + if (var->type()->isReference() || IsCompositeValueType(var->type())) __ get(var); - } // Get the value if needed. if (node->token() != TOK_ASSIGN) { @@ -247,8 +254,8 @@ if (node->token() != TOK_ASSIGN) __ dup(); - if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) - __ getfield(expr->fieldIndex(), expr->type()); + if (node->token() != TOK_ASSIGN || IsCompositeValueType(left)) + __ getfield(expr->fieldIndex(), left); } else { IndexExpression *index = node->lvalue()->toIndexExpression(); __ note_position(index->pos()); @@ -259,14 +266,14 @@ if (node->token() != TOK_ASSIGN) __ dup2(); - if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) - __ getelem(index->type()); + if (node->token() != TOK_ASSIGN || IsCompositeValueType(left)) + __ getelem(left); } if (node->token() == TOK_ASSIGN) { node->expression()->accept(this); } else { - visitForALU(node->type(), node->expression()); + visitForALU(left, node->expression()); TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS)); __ note_position(node->pos()); @@ -274,14 +281,16 @@ } // Emit the store. - if (type->isArray()) { - // Unlike references, which can only be computed from a NamePRoxy, - // arrays can be computed from multiple lvalue types. + if (left->isArray() && left->isFixedLength()) { + // (x = y) returns the left-hand side; if |x| is a fixed-length array, + // then |y| is as well, and we perform a deep copy. + assert(right->isFixedLength()); __ note_position(node->pos()); __ copyarray(); - } else if (type->isStruct()) { + } else if (left->isStruct()) { // Structs have value semantics, so emit a full copy. We don't break // this down into u-ops, to avoid unnecessary bytecode explosion. + assert(right->isStruct()); __ note_position(node->pos()); __ copystruct(); } else if (node->lvalue()->isNameProxy()) { @@ -296,10 +305,9 @@ __ set(var); } else if (node->lvalue()->isFieldExpression()) { FieldExpression *expr = node->lvalue()->toFieldExpression(); - __ setfield(expr->fieldIndex(), expr->type()); + __ setfield(expr->fieldIndex(), left); } else { - IndexExpression *index = node->lvalue()->toIndexExpression(); - __ setelem(index->type()); + __ setelem(left); } }